From 657742fda100cb89ec9ac59942c896ed1c6bf05c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Siatkowski?= Date: Thu, 29 Aug 2019 17:12:13 +0200 Subject: [PATCH] testing with docker --- .travis.yml | 6 - build.sbt | 15 +- src/test/scala/com/redis/PatternsSpec.scala | 7 +- src/test/scala/com/redis/PipelineSpec.scala | 3 +- src/test/scala/com/redis/PoolSpec.scala | 37 ++--- src/test/scala/com/redis/PubSubSpec.scala | 12 +- .../scala/com/redis/RedisClientSpec.scala | 22 ++- .../scala/com/redis/SerializationSpec.scala | 3 +- src/test/scala/com/redis/WatchSpec.scala | 30 +--- src/test/scala/com/redis/api/ApiSpec.scala | 2 +- .../scala/com/redis/api/BaseApiSpec.scala | 2 +- .../scala/com/redis/api/EvalApiSpec.scala | 2 +- src/test/scala/com/redis/api/GeoApiSpec.scala | 2 +- .../scala/com/redis/api/HashApiSpec.scala | 2 +- .../com/redis/api/HyperLogLogApiSpec.scala | 2 +- .../scala/com/redis/api/ListApiSpec.scala | 11 +- .../scala/com/redis/api/NodeApiSpec.scala | 2 +- src/test/scala/com/redis/api/SetApiSpec.scala | 2 +- .../com/redis/api/SortedSetApiSpec.scala | 134 +++++++++--------- .../scala/com/redis/api/StringApiSpec.scala | 2 +- .../cluster/ClusterIncompatibleTests.scala | 2 +- .../cluster/ClusterUnimplementedMethods.scala | 2 +- .../cluster/CommonRedisClusterSpec.scala | 8 +- .../com/redis/cluster/RedisClusterSpec.scala | 2 +- .../com/redis/common/IntClusterSpec.scala | 28 ++-- src/test/scala/com/redis/common/IntSpec.scala | 17 +-- .../scala/com/redis/common/RedisDocker.scala | 50 +++++++ .../com/redis/common/StringTypeData.scala | 2 +- .../redis/{ => ds}/BlockingDequeSpec.scala | 7 +- .../scala/com/redis/{ => ds}/DequeSpec.scala | 4 +- 30 files changed, 227 insertions(+), 193 deletions(-) create mode 100644 src/test/scala/com/redis/common/RedisDocker.scala rename src/test/scala/com/redis/{ => ds}/BlockingDequeSpec.scala (81%) rename src/test/scala/com/redis/{ => ds}/DequeSpec.scala (90%) diff --git a/.travis.yml b/.travis.yml index 848af5ee..8095facd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,9 +7,3 @@ script: jdk: - openjdk8 - openjdk11 -services: - - redis-server -before_script: - - sudo redis-server /etc/redis/redis.conf --port 6380 - - sudo redis-server /etc/redis/redis.conf --port 6381 - - sudo redis-server /etc/redis/redis.conf --port 6382 diff --git a/build.sbt b/build.sbt index 0e1ec9d8..b63fae2f 100644 --- a/build.sbt +++ b/build.sbt @@ -15,6 +15,12 @@ lazy val commonSettings: Seq[Setting[_]] = Seq( ) ) +def dockerTestKit(version: String): Seq[ModuleID] = { + Seq("docker-testkit-scalatest", "docker-testkit-impl-docker-java").map("com.whisk" %% _ % version % Test) :+ + // https://github.com/eclipse-ee4j/jaxb-ri/issues/1222 + "javax.xml.bind" % "jaxb-api" % "2.3.1" % Test +} + lazy val coreSettings = commonSettings ++ Seq( name := "RedisClient", libraryDependencies ++= Seq( @@ -22,9 +28,14 @@ lazy val coreSettings = commonSettings ++ Seq( "org.slf4j" % "slf4j-api" % "1.7.26", "org.slf4j" % "slf4j-log4j12" % "1.7.26" % "provided", "log4j" % "log4j" % "1.2.17" % "provided", - "org.scalatest" %% "scalatest" % "3.0.8" % "test"), + "org.scalatest" %% "scalatest" % "3.0.8" % "test" + ) ++ + (scalaBinaryVersion.value match { + case "2.10" => dockerTestKit("0.9.8") + case _ => dockerTestKit("0.9.9") + }) + , - parallelExecution in Test := false, publishTo := version { (v: String) => val nexus = "https://oss.sonatype.org/" if (v.trim.endsWith("SNAPSHOT")) Some("snapshots" at nexus + "content/repositories/snapshots") diff --git a/src/test/scala/com/redis/PatternsSpec.scala b/src/test/scala/com/redis/PatternsSpec.scala index bb566cb3..5b4405a1 100644 --- a/src/test/scala/com/redis/PatternsSpec.scala +++ b/src/test/scala/com/redis/PatternsSpec.scala @@ -1,14 +1,15 @@ package com.redis import com.redis.Patterns._ -import org.scalatest.{BeforeAndAfterAll, BeforeAndAfterEach, FunSpec, Matchers} +import com.redis.common.RedisDocker +import org.scalatest.{BeforeAndAfterEach, FunSpec, Matchers} class PatternsSpec extends FunSpec with Matchers with BeforeAndAfterEach - with BeforeAndAfterAll { + with RedisDocker { - implicit val clients = new RedisClientPool("localhost", 6379) + implicit lazy val clients = new RedisClientPool(redisContainerHost, redisContainerPort) override def afterEach = clients.withClient{ client => client.flushdb diff --git a/src/test/scala/com/redis/PipelineSpec.scala b/src/test/scala/com/redis/PipelineSpec.scala index 5471ffac..a73321e5 100644 --- a/src/test/scala/com/redis/PipelineSpec.scala +++ b/src/test/scala/com/redis/PipelineSpec.scala @@ -10,7 +10,8 @@ class PipelineSpec extends FunSpec with IntSpec with Inside { - val r = new RedisClient("localhost", 6379) + override protected lazy val r: RedisClient = + new RedisClient(redisContainerHost, redisContainerPort) describe("pipeline1") { it("should do pipelined commands") { diff --git a/src/test/scala/com/redis/PoolSpec.scala b/src/test/scala/com/redis/PoolSpec.scala index 39cd6055..7359b167 100644 --- a/src/test/scala/com/redis/PoolSpec.scala +++ b/src/test/scala/com/redis/PoolSpec.scala @@ -1,31 +1,34 @@ package com.redis -import org.scalatest.FunSpec -import org.scalatest.BeforeAndAfterEach -import org.scalatest.BeforeAndAfterAll -import org.scalatest.Matchers +import com.redis.common.RedisDocker +import org.scalatest.{BeforeAndAfterEach, FunSpec, Matchers} import scala.concurrent._ import scala.concurrent.duration._ -import ExecutionContext.Implicits.global class PoolSpec extends FunSpec with Matchers with BeforeAndAfterEach - with BeforeAndAfterAll { + with RedisDocker { - implicit val clients = new RedisClientPool("localhost", 6379) + implicit lazy val clients: RedisClientPool = new RedisClientPool(redisContainerHost, redisContainerPort) - override def beforeEach = { + override protected def beforeEach(): Unit = { + super.beforeEach() + clients.port should be > 0 // initialize lazy val hack :( } - override def afterEach = clients.withClient{ - client => client.flushdb + override def afterEach(): Unit = { + clients.withClient{ + client => client.flushdb + } + super.afterEach() } - override def afterAll = { + override def afterAll(): Unit = { clients.withClient{ client => client.disconnect } clients.close + super.afterAll() } def lp(msgs: List[String]) = { @@ -69,18 +72,6 @@ class PoolSpec extends FunSpec } } - def leftp(msgs: List[String]) = { - clients.withClient { - client => { - val ln = new scala.util.Random().nextString(10) - msgs.foreach(client.lpush(ln, _)) - val len = client.llen(ln) -println(len) - len - } - } - } - import Bench._ private val amountMultiplier = 1 // unit test multiplier diff --git a/src/test/scala/com/redis/PubSubSpec.scala b/src/test/scala/com/redis/PubSubSpec.scala index b3a9ddb5..0d12e522 100644 --- a/src/test/scala/com/redis/PubSubSpec.scala +++ b/src/test/scala/com/redis/PubSubSpec.scala @@ -1,18 +1,16 @@ package com.redis -import org.scalatest.FunSpec -import org.scalatest.BeforeAndAfterAll -import org.scalatest.Matchers +import com.redis.common.RedisDocker +import org.scalatest.{FunSpec, Matchers} class PubSubSpec extends FunSpec with Matchers - with BeforeAndAfterAll { + with RedisDocker { - val r = new RedisClient("localhost", 6379) - val t = new RedisClient("localhost", 6379) + lazy val r = new RedisClient(redisContainerHost, redisContainerPort) + lazy val t = new RedisClient(redisContainerHost, redisContainerPort) override def afterAll(): Unit = { - r.flushall r.close() t.close() } diff --git a/src/test/scala/com/redis/RedisClientSpec.scala b/src/test/scala/com/redis/RedisClientSpec.scala index f97101aa..5eb3f429 100644 --- a/src/test/scala/com/redis/RedisClientSpec.scala +++ b/src/test/scala/com/redis/RedisClientSpec.scala @@ -9,29 +9,36 @@ import org.scalatest.Matchers class RedisClientSpec extends FunSpec with Matchers with ApiSpec { - override val r: RedisClient = - new RedisClient("localhost", 6379) + override protected lazy val r: RedisClient = + new RedisClient(redisContainerHost, redisContainerPort) + + private lazy val redisUrl = s"$redisContainerHost:$redisContainerPort" describe("constructor") { it("should parse the db-number from the path of connection uri") { - val client = new RedisClient(new URI("redis://localhost:6379/4")) + val client = new RedisClient(new URI(s"redis://$redisUrl/4")) client.database shouldBe 4 + client.close() } it("should default to db 0 for connection uri without db-number") { - val client = new RedisClient(new URI("redis://localhost:6379")) + val client = new RedisClient(new URI(s"redis://$redisUrl")) client.database shouldBe 0 + client.close() } } describe("toString") { it("should include the db-number") { - new RedisClient("localhost", 6379, 1).toString shouldBe "localhost:6379/1" + val c = new RedisClient(redisContainerHost, redisContainerPort, 1) + c.toString shouldBe s"$redisUrl/1" + c.close() } } describe("test subscribe") { - val r = new RedisClient("localhost", 6379) + it("should subscribe") { + val r = new RedisClient(redisContainerHost, redisContainerPort) println(r.get("vvl:qm")) @@ -58,5 +65,6 @@ class RedisClientSpec extends FunSpec Thread.sleep(3000) r.get("vvl:qm") - } + r.close() + }} } diff --git a/src/test/scala/com/redis/SerializationSpec.scala b/src/test/scala/com/redis/SerializationSpec.scala index ce6da770..d1f69c29 100644 --- a/src/test/scala/com/redis/SerializationSpec.scala +++ b/src/test/scala/com/redis/SerializationSpec.scala @@ -9,7 +9,8 @@ class SerializationSpec extends FunSpec with Matchers with IntSpec { - val r = new RedisClient("localhost", 6379) + override protected lazy val r: RedisClient = + new RedisClient(redisContainerHost, redisContainerPort) it("should not conflict when using all built in parsers") { import Parse.Implicits._ diff --git a/src/test/scala/com/redis/WatchSpec.scala b/src/test/scala/com/redis/WatchSpec.scala index fedf9334..b6c877f8 100644 --- a/src/test/scala/com/redis/WatchSpec.scala +++ b/src/test/scala/com/redis/WatchSpec.scala @@ -1,40 +1,23 @@ package com.redis -import org.scalatest.FunSpec -import org.scalatest.BeforeAndAfterEach -import org.scalatest.BeforeAndAfterAll -import org.scalatest.Matchers -import org.scalatest.concurrent.ScalaFutures -import org.scalatest.time.{Milliseconds, Seconds => SSeconds, Span} +import com.redis.common.RedisDocker +import org.scalatest.{FunSpec, Matchers} import scala.concurrent.Future -import scala.concurrent.ExecutionContext.Implicits.global -class WatchSpec extends FunSpec with ScalaFutures +class WatchSpec extends FunSpec with Matchers - with BeforeAndAfterEach - with BeforeAndAfterAll { - - implicit val pc: PatienceConfig = PatienceConfig(Span(5, SSeconds), Span(100, Milliseconds)) - - val clients: RedisClientPool = new RedisClientPool("localhost", 6379) - - override def beforeAll(): Unit = { - clients.withClient(_.flushall) - } - - override def afterAll(): Unit = { - clients.close - } + with RedisDocker { describe("watch") { it("should fail a transaction if modified from another client") { + val clients = new RedisClientPool(redisContainerHost, redisContainerPort) val p1: Future[Option[List[Any]]] = Future { clients.withClient { client => client.watch("key") client.pipeline { p => p.set("key", "debasish") - Thread.sleep(50) + Thread.sleep(100) p.get("key") p.get("key1") } @@ -50,6 +33,7 @@ class WatchSpec extends FunSpec with ScalaFutures p2.futureValue should equal(true) p1.futureValue should equal(None) + clients.close } } } diff --git a/src/test/scala/com/redis/api/ApiSpec.scala b/src/test/scala/com/redis/api/ApiSpec.scala index ed208e66..005f8239 100644 --- a/src/test/scala/com/redis/api/ApiSpec.scala +++ b/src/test/scala/com/redis/api/ApiSpec.scala @@ -12,7 +12,7 @@ trait ApiSpec with SortedSetApiSpec with StringApiSpec { - override val r: AutoCloseable + override protected def r: AutoCloseable with BaseApi with EvalApi with GeoApi diff --git a/src/test/scala/com/redis/api/BaseApiSpec.scala b/src/test/scala/com/redis/api/BaseApiSpec.scala index e8ddc1be..5120daaa 100644 --- a/src/test/scala/com/redis/api/BaseApiSpec.scala +++ b/src/test/scala/com/redis/api/BaseApiSpec.scala @@ -13,7 +13,7 @@ trait BaseApiSpec extends FunSpec with IntSpec { // todo: remove SetApi, HashApi and ListApi - override val r: BaseApi with StringApi with AutoCloseable with SetApi with HashApi with ListApi + override protected def r: BaseApi with StringApi with AutoCloseable with SetApi with HashApi with ListApi dbsize() del() diff --git a/src/test/scala/com/redis/api/EvalApiSpec.scala b/src/test/scala/com/redis/api/EvalApiSpec.scala index b90f4d67..d2b5278a 100644 --- a/src/test/scala/com/redis/api/EvalApiSpec.scala +++ b/src/test/scala/com/redis/api/EvalApiSpec.scala @@ -10,7 +10,7 @@ trait EvalApiSpec extends FunSpec with Matchers with IntSpec { - override val r: BaseApi with StringApi with EvalApi with ListApi with SortedSetApi with AutoCloseable + override protected def r: BaseApi with StringApi with EvalApi with ListApi with SortedSetApi with AutoCloseable describe("eval") { getStringReply() diff --git a/src/test/scala/com/redis/api/GeoApiSpec.scala b/src/test/scala/com/redis/api/GeoApiSpec.scala index dc1783b5..c7b157d2 100644 --- a/src/test/scala/com/redis/api/GeoApiSpec.scala +++ b/src/test/scala/com/redis/api/GeoApiSpec.scala @@ -8,7 +8,7 @@ trait GeoApiSpec extends FunSpec with Matchers with IntSpec { - override val r: BaseApi with StringApi with GeoApi with AutoCloseable + override protected def r: BaseApi with StringApi with GeoApi with AutoCloseable geoadd() geopos() diff --git a/src/test/scala/com/redis/api/HashApiSpec.scala b/src/test/scala/com/redis/api/HashApiSpec.scala index faa71005..b8d6e669 100644 --- a/src/test/scala/com/redis/api/HashApiSpec.scala +++ b/src/test/scala/com/redis/api/HashApiSpec.scala @@ -8,7 +8,7 @@ trait HashApiSpec extends FunSpec with Matchers with IntSpec { - override val r: BaseApi with StringApi with HashApi with AutoCloseable + override protected def r: BaseApi with StringApi with HashApi with AutoCloseable hset() hset1() diff --git a/src/test/scala/com/redis/api/HyperLogLogApiSpec.scala b/src/test/scala/com/redis/api/HyperLogLogApiSpec.scala index 2896d3b8..7b8d9ef4 100644 --- a/src/test/scala/com/redis/api/HyperLogLogApiSpec.scala +++ b/src/test/scala/com/redis/api/HyperLogLogApiSpec.scala @@ -8,7 +8,7 @@ trait HyperLogLogApiSpec extends FunSpec with Matchers with IntSpec { - override val r: BaseApi with StringApi with HyperLogLogApi with AutoCloseable + override protected def r: BaseApi with StringApi with HyperLogLogApi with AutoCloseable pfadd() pfcount() diff --git a/src/test/scala/com/redis/api/ListApiSpec.scala b/src/test/scala/com/redis/api/ListApiSpec.scala index 4c9df57e..a6c4dacb 100644 --- a/src/test/scala/com/redis/api/ListApiSpec.scala +++ b/src/test/scala/com/redis/api/ListApiSpec.scala @@ -3,10 +3,8 @@ package com.redis.api import com.redis.RedisClient import com.redis.common.IntSpec import org.scalatest.concurrent.ScalaFutures -import org.scalatest.time.{Milliseconds, Span, Seconds => SSeconds} import org.scalatest.{BeforeAndAfterEach, FunSpec, Matchers} -import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -15,9 +13,7 @@ trait ListApiSpec extends FunSpec with ScalaFutures with BeforeAndAfterEach with IntSpec { - implicit val pc: PatienceConfig = PatienceConfig(Span(3, SSeconds), Span(100, Milliseconds)) - - override val r: BaseApi with StringApi with ListApi with AutoCloseable + override protected def r: BaseApi with StringApi with ListApi with AutoCloseable blpop() brpoplpush() @@ -397,7 +393,7 @@ trait ListApiSpec extends FunSpec with ScalaFutures } it("should pop blockingly") { - val r1 = new RedisClient("localhost", 6379) + val r1 = new RedisClient(redisContainerHost, redisContainerPort) val testVal: Future[Option[String]] = Future { r1.brpoplpush("l1", "l2", 3) should equal(Some("a")) @@ -423,11 +419,10 @@ trait ListApiSpec extends FunSpec with ScalaFutures } } - // todo: this does not fail the ScalaTest even if the matcher fails protected def blpop(): Unit = { describe("blpop") { it("should pop in a blocking mode") { - val r1 = new RedisClient("localhost", 6379) + val r1 = new RedisClient(redisContainerHost, redisContainerPort) val blpopV: Future[Option[(String, String)]] = Future { r1.blpop(3, "l1", "l2") diff --git a/src/test/scala/com/redis/api/NodeApiSpec.scala b/src/test/scala/com/redis/api/NodeApiSpec.scala index d5eb0849..c94c25ea 100644 --- a/src/test/scala/com/redis/api/NodeApiSpec.scala +++ b/src/test/scala/com/redis/api/NodeApiSpec.scala @@ -7,7 +7,7 @@ import org.scalatest.{FunSpec, Matchers} trait NodeApiSpec extends FunSpec with Matchers with IntSpec { - override val r: BaseApi with StringApi with NodeApi with AutoCloseable + override protected def r: BaseApi with StringApi with NodeApi with AutoCloseable describe("NodeApiTest") { diff --git a/src/test/scala/com/redis/api/SetApiSpec.scala b/src/test/scala/com/redis/api/SetApiSpec.scala index 2b2397cd..fe300b20 100644 --- a/src/test/scala/com/redis/api/SetApiSpec.scala +++ b/src/test/scala/com/redis/api/SetApiSpec.scala @@ -8,7 +8,7 @@ trait SetApiSpec extends FunSpec with IntSpec { // todo: remove HashApi, ListApi - override val r: BaseApi with StringApi with SetApi with AutoCloseable with HashApi with ListApi + override protected def r: BaseApi with StringApi with SetApi with AutoCloseable with HashApi with ListApi sadd() saddWithVariadicArguments() diff --git a/src/test/scala/com/redis/api/SortedSetApiSpec.scala b/src/test/scala/com/redis/api/SortedSetApiSpec.scala index 92c80ad8..3420a85e 100644 --- a/src/test/scala/com/redis/api/SortedSetApiSpec.scala +++ b/src/test/scala/com/redis/api/SortedSetApiSpec.scala @@ -10,7 +10,7 @@ trait SortedSetApiSpec extends FunSpec with Matchers with IntSpec { - override val r: BaseApi with StringApi with SortedSetApi with AutoCloseable + override protected def r: BaseApi with StringApi with SortedSetApi with AutoCloseable zrangebylexT() zaddT() @@ -25,27 +25,25 @@ trait SortedSetApiSpec extends FunSpec zrangebyscoreT() zrangebyscoreWithScoreT() - import r._ - private def add = { - zadd("hackers", 1965, "yukihiro matsumoto") should equal(Some(1)) - zadd("hackers", 1953, "richard stallman", (1916, "claude shannon"), (1969, "linus torvalds"), (1940, "alan kay"), (1912, "alan turing")) should equal(Some(5)) + r.zadd("hackers", 1965, "yukihiro matsumoto") should equal(Some(1)) + r.zadd("hackers", 1953, "richard stallman", (1916, "claude shannon"), (1969, "linus torvalds"), (1940, "alan kay"), (1912, "alan turing")) should equal(Some(5)) } private def addKeysWithSameScore = { - zadd("hackers-joker", 0, "a", (0, "b"), (0, "c"), (0, "d")) + r.zadd("hackers-joker", 0, "a", (0, "b"), (0, "c"), (0, "d")) } protected def zrangebylexT(): Unit = { describe("zrangebylex") { it("should return the elements between min and max") { addKeysWithSameScore - zrangebylex("hackers-joker", "[a", "[b", None).get should equal(List("a", "b")) + r.zrangebylex("hackers-joker", "[a", "[b", None).get should equal(List("a", "b")) } it("should return the elements between min and max with offset and count") { addKeysWithSameScore - zrangebylex("hackers-joker", "[a", "[c", Some(0, 1)).get should equal(List("a")) + r.zrangebylex("hackers-joker", "[a", "[c", Some(0, 1)).get should equal(List("a")) } } } @@ -54,8 +52,8 @@ trait SortedSetApiSpec extends FunSpec describe("zadd") { it("should add based on proper sorted set semantics") { add - zadd("hackers", 1912, "alan turing") should equal(Some(0)) - zcard("hackers").get should equal(6) + r.zadd("hackers", 1912, "alan turing") should equal(Some(0)) + r.zcard("hackers").get should equal(6) } } } @@ -64,9 +62,9 @@ trait SortedSetApiSpec extends FunSpec describe("zrem") { it("should remove") { add - zrem("hackers", "alan turing") should equal(Some(1)) - zrem("hackers", "alan kay", "linus torvalds") should equal(Some(2)) - zrem("hackers", "alan kay", "linus torvalds") should equal(Some(0)) + r.zrem("hackers", "alan turing") should equal(Some(1)) + r.zrem("hackers", "alan kay", "linus torvalds") should equal(Some(2)) + r.zrem("hackers", "alan kay", "linus torvalds") should equal(Some(0)) } } } @@ -75,8 +73,8 @@ trait SortedSetApiSpec extends FunSpec describe("zrange") { it("should get the proper range") { add - zrange("hackers").get should have size (6) - zrangeWithScore("hackers").get should have size(6) + r.zrange("hackers").get should have size (6) + r.zrangeWithScore("hackers").get should have size(6) } } } @@ -85,8 +83,8 @@ trait SortedSetApiSpec extends FunSpec describe("zrank") { it ("should give proper rank") { add - zrank("hackers", "yukihiro matsumoto") should equal(Some(4)) - zrank("hackers", "yukihiro matsumoto", reverse = true) should equal(Some(1)) + r.zrank("hackers", "yukihiro matsumoto") should equal(Some(4)) + r.zrank("hackers", "yukihiro matsumoto", reverse = true) should equal(Some(1)) } } } @@ -95,7 +93,7 @@ trait SortedSetApiSpec extends FunSpec describe("zremrangebyrank") { it ("should remove based on rank range") { add - zremrangebyrank("hackers", 0, 2) should equal(Some(3)) + r.zremrangebyrank("hackers", 0, 2) should equal(Some(3)) } } } @@ -104,8 +102,8 @@ trait SortedSetApiSpec extends FunSpec describe("zremrangebyscore") { it ("should remove based on score range") { add - zremrangebyscore("hackers", 1912, 1940) should equal(Some(3)) - zremrangebyscore("hackers", 0, 3) should equal(Some(0)) + r.zremrangebyscore("hackers", 1912, 1940) should equal(Some(3)) + r.zremrangebyscore("hackers", 0, 3) should equal(Some(0)) } } } @@ -113,22 +111,22 @@ trait SortedSetApiSpec extends FunSpec protected def zunionT(): Unit = { describe("zunion") { it ("should do a union") { - zadd("hackers 1", 1965, "yukihiro matsumoto") should equal(Some(1)) - zadd("hackers 1", 1953, "richard stallman") should equal(Some(1)) - zadd("hackers 2", 1916, "claude shannon") should equal(Some(1)) - zadd("hackers 2", 1969, "linus torvalds") should equal(Some(1)) - zadd("hackers 3", 1940, "alan kay") should equal(Some(1)) - zadd("hackers 4", 1912, "alan turing") should equal(Some(1)) + r.zadd("hackers 1", 1965, "yukihiro matsumoto") should equal(Some(1)) + r.zadd("hackers 1", 1953, "richard stallman") should equal(Some(1)) + r.zadd("hackers 2", 1916, "claude shannon") should equal(Some(1)) + r.zadd("hackers 2", 1969, "linus torvalds") should equal(Some(1)) + r.zadd("hackers 3", 1940, "alan kay") should equal(Some(1)) + r.zadd("hackers 4", 1912, "alan turing") should equal(Some(1)) // union with weight = 1 - zunionstore("hackers", List("hackers 1", "hackers 2", "hackers 3", "hackers 4")) should equal(Some(6)) - zcard("hackers") should equal(Some(6)) + r.zunionstore("hackers", List("hackers 1", "hackers 2", "hackers 3", "hackers 4")) should equal(Some(6)) + r.zcard("hackers") should equal(Some(6)) - zrangeWithScore("hackers").get.map(_._2) should equal(List(1912, 1916, 1940, 1953, 1965, 1969)) + r.zrangeWithScore("hackers").get.map(_._2) should equal(List(1912, 1916, 1940, 1953, 1965, 1969)) // union with modified weights - zunionstoreWeighted("hackers weighted", Map("hackers 1" -> 1.0, "hackers 2" -> 2.0, "hackers 3" -> 3.0, "hackers 4" -> 4.0)) should equal(Some(6)) - zrangeWithScore("hackers weighted").get.map(_._2.toInt) should equal(List(1953, 1965, 3832, 3938, 5820, 7648)) + r.zunionstoreWeighted("hackers weighted", Map("hackers 1" -> 1.0, "hackers 2" -> 2.0, "hackers 3" -> 3.0, "hackers 4" -> 4.0)) should equal(Some(6)) + r.zrangeWithScore("hackers weighted").get.map(_._2.toInt) should equal(List(1953, 1965, 3832, 3938, 5820, 7648)) } } } @@ -136,35 +134,35 @@ trait SortedSetApiSpec extends FunSpec protected def zinterT(): Unit = { describe("zinter") { it ("should do an intersection") { - zadd("hackers", 1912, "alan turing") should equal(Some(1)) - zadd("hackers", 1916, "claude shannon") should equal(Some(1)) - zadd("hackers", 1927, "john mccarthy") should equal(Some(1)) - zadd("hackers", 1940, "alan kay") should equal(Some(1)) - zadd("hackers", 1953, "richard stallman") should equal(Some(1)) - zadd("hackers", 1954, "larry wall") should equal(Some(1)) - zadd("hackers", 1956, "guido van rossum") should equal(Some(1)) - zadd("hackers", 1965, "paul graham") should equal(Some(1)) - zadd("hackers", 1965, "yukihiro matsumoto") should equal(Some(1)) - zadd("hackers", 1969, "linus torvalds") should equal(Some(1)) - - zadd("baby boomers", 1948, "phillip bobbit") should equal(Some(1)) - zadd("baby boomers", 1953, "richard stallman") should equal(Some(1)) - zadd("baby boomers", 1954, "cass sunstein") should equal(Some(1)) - zadd("baby boomers", 1954, "larry wall") should equal(Some(1)) - zadd("baby boomers", 1956, "guido van rossum") should equal(Some(1)) - zadd("baby boomers", 1961, "lawrence lessig") should equal(Some(1)) - zadd("baby boomers", 1965, "paul graham") should equal(Some(1)) - zadd("baby boomers", 1965, "yukihiro matsumoto") should equal(Some(1)) + r.zadd("hackers", 1912, "alan turing") should equal(Some(1)) + r.zadd("hackers", 1916, "claude shannon") should equal(Some(1)) + r.zadd("hackers", 1927, "john mccarthy") should equal(Some(1)) + r.zadd("hackers", 1940, "alan kay") should equal(Some(1)) + r.zadd("hackers", 1953, "richard stallman") should equal(Some(1)) + r.zadd("hackers", 1954, "larry wall") should equal(Some(1)) + r.zadd("hackers", 1956, "guido van rossum") should equal(Some(1)) + r.zadd("hackers", 1965, "paul graham") should equal(Some(1)) + r.zadd("hackers", 1965, "yukihiro matsumoto") should equal(Some(1)) + r.zadd("hackers", 1969, "linus torvalds") should equal(Some(1)) + + r.zadd("baby boomers", 1948, "phillip bobbit") should equal(Some(1)) + r.zadd("baby boomers", 1953, "richard stallman") should equal(Some(1)) + r.zadd("baby boomers", 1954, "cass sunstein") should equal(Some(1)) + r.zadd("baby boomers", 1954, "larry wall") should equal(Some(1)) + r.zadd("baby boomers", 1956, "guido van rossum") should equal(Some(1)) + r.zadd("baby boomers", 1961, "lawrence lessig") should equal(Some(1)) + r.zadd("baby boomers", 1965, "paul graham") should equal(Some(1)) + r.zadd("baby boomers", 1965, "yukihiro matsumoto") should equal(Some(1)) // intersection with weight = 1 - zinterstore("baby boomer hackers", List("hackers", "baby boomers")) should equal(Some(5)) - zcard("baby boomer hackers") should equal(Some(5)) + r.zinterstore("baby boomer hackers", List("hackers", "baby boomers")) should equal(Some(5)) + r.zcard("baby boomer hackers") should equal(Some(5)) - zrange("baby boomer hackers").get should equal(List("richard stallman", "larry wall", "guido van rossum", "paul graham", "yukihiro matsumoto")) + r.zrange("baby boomer hackers").get should equal(List("richard stallman", "larry wall", "guido van rossum", "paul graham", "yukihiro matsumoto")) // intersection with modified weights - zinterstoreWeighted("baby boomer hackers weighted", Map("hackers" -> 0.5, "baby boomers" -> 0.5)) should equal(Some(5)) - zrangeWithScore("baby boomer hackers weighted").get.map(_._2.toInt) should equal(List(1953, 1954, 1956, 1965, 1965)) + r.zinterstoreWeighted("baby boomer hackers weighted", Map("hackers" -> 0.5, "baby boomers" -> 0.5)) should equal(Some(5)) + r.zrangeWithScore("baby boomer hackers weighted").get.map(_._2.toInt) should equal(List(1953, 1954, 1956, 1965, 1965)) } } } @@ -174,7 +172,7 @@ trait SortedSetApiSpec extends FunSpec it ("should return the number of elements between min and max") { add - zcount("hackers", 1912, 1920) should equal(Some(2)) + r.zcount("hackers", 1912, 1920) should equal(Some(2)) } } } @@ -184,32 +182,32 @@ trait SortedSetApiSpec extends FunSpec it ("should return the elements between min and max") { add - zrangebyscore("hackers", 1940, true, 1969, true, None).get should equal( + r.zrangebyscore("hackers", 1940, true, 1969, true, None).get should equal( List("alan kay", "richard stallman", "yukihiro matsumoto", "linus torvalds")) - zrangebyscore("hackers", 1940, true, 1969, true, None, DESC).get should equal( + r.zrangebyscore("hackers", 1940, true, 1969, true, None, DESC).get should equal( List("linus torvalds", "yukihiro matsumoto", "richard stallman","alan kay")) } it("should return the elements between min and max and allow offset and limit") { add - zrangebyscore("hackers", 1940, true, 1969, true, Some(0, 2)).get should equal( + r.zrangebyscore("hackers", 1940, true, 1969, true, Some(0, 2)).get should equal( List("alan kay", "richard stallman")) - zrangebyscore("hackers", 1940, true, 1969, true, Some(0, 2), DESC).get should equal( + r.zrangebyscore("hackers", 1940, true, 1969, true, Some(0, 2), DESC).get should equal( List("linus torvalds", "yukihiro matsumoto")) - zrangebyscore("hackers", 1940, true, 1969, true, Some(3, 1)).get should equal ( + r.zrangebyscore("hackers", 1940, true, 1969, true, Some(3, 1)).get should equal ( List("linus torvalds")) - zrangebyscore("hackers", 1940, true, 1969, true, Some(3, 1), DESC).get should equal ( + r.zrangebyscore("hackers", 1940, true, 1969, true, Some(3, 1), DESC).get should equal ( List("alan kay")) - zrangebyscore("hackers", 1940, false, 1969, true, Some(0, 2)).get should equal ( + r.zrangebyscore("hackers", 1940, false, 1969, true, Some(0, 2)).get should equal ( List("richard stallman", "yukihiro matsumoto")) - zrangebyscore("hackers", 1940, true, 1969, false, Some(0, 2), DESC).get should equal ( + r.zrangebyscore("hackers", 1940, true, 1969, false, Some(0, 2), DESC).get should equal ( List("yukihiro matsumoto", "richard stallman")) } } @@ -220,16 +218,16 @@ trait SortedSetApiSpec extends FunSpec it ("should return the elements between min and max") { add - zrangebyscoreWithScore("hackers", 1940, true, 1969, true, None).get should equal( + r.zrangebyscoreWithScore("hackers", 1940, true, 1969, true, None).get should equal( List(("alan kay", 1940.0), ("richard stallman", 1953.0), ("yukihiro matsumoto", 1965.0), ("linus torvalds", 1969.0))) - zrangebyscoreWithScore("hackers", 1940, true, 1969, true, None, DESC).get should equal( + r.zrangebyscoreWithScore("hackers", 1940, true, 1969, true, None, DESC).get should equal( List(("linus torvalds", 1969.0), ("yukihiro matsumoto", 1965.0), ("richard stallman", 1953.0),("alan kay", 1940.0))) - zrangebyscoreWithScore("hackers", 1940, true, 1969, true, Some(3, 1)).get should equal ( + r.zrangebyscoreWithScore("hackers", 1940, true, 1969, true, Some(3, 1)).get should equal ( List(("linus torvalds", 1969.0))) - zrangebyscoreWithScore("hackers", 1940, true, 1969, true, Some(3, 1), DESC).get should equal ( + r.zrangebyscoreWithScore("hackers", 1940, true, 1969, true, Some(3, 1), DESC).get should equal ( List(("alan kay", 1940.0))) } } diff --git a/src/test/scala/com/redis/api/StringApiSpec.scala b/src/test/scala/com/redis/api/StringApiSpec.scala index 55f8ebd7..ee7946fd 100644 --- a/src/test/scala/com/redis/api/StringApiSpec.scala +++ b/src/test/scala/com/redis/api/StringApiSpec.scala @@ -12,7 +12,7 @@ trait StringApiSpec extends FunSpec with Matchers with IntSpec { - override val r: BaseApi with StringApi with AutoCloseable + override protected def r: BaseApi with StringApi with AutoCloseable append() bitcount() diff --git a/src/test/scala/com/redis/cluster/ClusterIncompatibleTests.scala b/src/test/scala/com/redis/cluster/ClusterIncompatibleTests.scala index 153e281c..a26d9bfa 100644 --- a/src/test/scala/com/redis/cluster/ClusterIncompatibleTests.scala +++ b/src/test/scala/com/redis/cluster/ClusterIncompatibleTests.scala @@ -17,7 +17,7 @@ trait ClusterIncompatibleTests with SortedSetApiSpec with StringApiSpec { - override val r: AutoCloseable + override protected def r: AutoCloseable with BaseApi with EvalApi // with GeoApi diff --git a/src/test/scala/com/redis/cluster/ClusterUnimplementedMethods.scala b/src/test/scala/com/redis/cluster/ClusterUnimplementedMethods.scala index b088d840..9b17f8cc 100644 --- a/src/test/scala/com/redis/cluster/ClusterUnimplementedMethods.scala +++ b/src/test/scala/com/redis/cluster/ClusterUnimplementedMethods.scala @@ -18,7 +18,7 @@ trait ClusterUnimplementedMethods with SortedSetApiSpec with StringApiSpec { - override val r: AutoCloseable + override protected def r: AutoCloseable with BaseApi with EvalApi // with GeoApi diff --git a/src/test/scala/com/redis/cluster/CommonRedisClusterSpec.scala b/src/test/scala/com/redis/cluster/CommonRedisClusterSpec.scala index 0fe1ae70..282caec2 100644 --- a/src/test/scala/com/redis/cluster/CommonRedisClusterSpec.scala +++ b/src/test/scala/com/redis/cluster/CommonRedisClusterSpec.scala @@ -10,7 +10,7 @@ import scala.collection.mutable.ArrayBuffer // todo: remove, test every API separately @deprecated trait CommonRedisClusterSpec[A] extends FunSpec with Matchers with IntClusterSpec { - override val r = rProvider() + override lazy val r = rProvider() def rProvider(): AutoCloseable with RedisClusterOps with WithHashRing[A] with BaseApi with HashApi with ListApi with NodeApi with SetApi with SortedSetApi with StringApi @@ -120,12 +120,12 @@ import scala.collection.mutable.ArrayBuffer //simulate the same value is duplicated to slave //for test, don't set to master, just to make sure the expected value is loaded from slave - val redisClient = new RedisClient("localhost", 6382) + val redisClient = new RedisClient(redisContainerHost, redisContainerPort(dockerContainers.head)) redisClient.set("testkey1", "testvalue1") //replaced master with slave on the same node - r.replaceServer(ClusterNode(nodename, "localhost", 6382)) - r.nodeForKey("testkey1").port should equal(6382) + r.replaceServer(ClusterNode(nodename, redisContainerHost, redisContainerPort(dockerContainers.head))) + r.nodeForKey("testkey1").port should equal(redisContainerPort(dockerContainers.head)) // todo: special check for RedisCluster specialClusterCheck(r.hr.cluster, nodename) diff --git a/src/test/scala/com/redis/cluster/RedisClusterSpec.scala b/src/test/scala/com/redis/cluster/RedisClusterSpec.scala index a5dd552f..f27233ec 100644 --- a/src/test/scala/com/redis/cluster/RedisClusterSpec.scala +++ b/src/test/scala/com/redis/cluster/RedisClusterSpec.scala @@ -19,5 +19,5 @@ class RedisClusterSpec extends FunSpec } override def specialClusterCheck(cluster: ArrayBuffer[IdentifiableRedisClientPool], nodename: String): Assertion = - cluster.find(_.node.nodename.equals(nodename)).get.port should equal(6382) + cluster.find(_.node.nodename.equals(nodename)).get.port should equal(redisContainerPort(dockerContainers.head)) } diff --git a/src/test/scala/com/redis/common/IntClusterSpec.scala b/src/test/scala/com/redis/common/IntClusterSpec.scala index 7804b021..02c57504 100644 --- a/src/test/scala/com/redis/common/IntClusterSpec.scala +++ b/src/test/scala/com/redis/common/IntClusterSpec.scala @@ -1,20 +1,32 @@ package com.redis.common +import com.redis.api.BaseApi import com.redis.cluster.ClusterNode import com.redis.serialization.Format -import org.scalatest.Suite +import org.scalatest.{BeforeAndAfterEach, Suite} -trait IntClusterSpec extends IntSpec { +trait IntClusterSpec extends BeforeAndAfterEach with RedisDockerCluster { that: Suite => - protected val nodes: List[ClusterNode] = List( - ClusterNode("node1", "localhost", 6379), - ClusterNode("node2", "localhost", 6380), - ClusterNode("node3", "localhost", 6381), - ClusterNode("node4", "localhost", 6382) - ) + protected def r: BaseApi with AutoCloseable + private val nodeNamePrefix = "node" + + protected lazy val nodes: List[ClusterNode] = + runningContainers.zipWithIndex.map { case (c, i) => + ClusterNode(s"$nodeNamePrefix$i", redisContainerHost, redisContainerPort(c)) + } def formattedKey(key: Any)(implicit format: Format): Array[Byte] = { format(key) } + + override def afterAll: Unit = { + r.close() + super.afterAll() + } + + override def afterEach: Unit = { + r.flushall + super.afterEach() + } } diff --git a/src/test/scala/com/redis/common/IntSpec.scala b/src/test/scala/com/redis/common/IntSpec.scala index 37527932..7e91077f 100644 --- a/src/test/scala/com/redis/common/IntSpec.scala +++ b/src/test/scala/com/redis/common/IntSpec.scala @@ -1,29 +1,18 @@ package com.redis.common import com.redis.api.BaseApi -import org.scalatest.{BeforeAndAfterAll, BeforeAndAfterEach, Suite} +import org.scalatest.{BeforeAndAfterEach, Suite} -trait IntSpec extends BeforeAndAfterAll with BeforeAndAfterEach { +trait IntSpec extends BeforeAndAfterEach with RedisDocker { that: Suite => - val r: BaseApi with AutoCloseable + protected def r: BaseApi with AutoCloseable override def afterAll: Unit = { - r.flushall r.close() super.afterAll() } - override def beforeAll: Unit = { - super.beforeAll() - r.flushall - } - - override def beforeEach: Unit = { - super.beforeEach() - r.flushall - } - override def afterEach: Unit = { r.flushall super.afterEach() diff --git a/src/test/scala/com/redis/common/RedisDocker.scala b/src/test/scala/com/redis/common/RedisDocker.scala new file mode 100644 index 00000000..031be258 --- /dev/null +++ b/src/test/scala/com/redis/common/RedisDocker.scala @@ -0,0 +1,50 @@ +package com.redis.common + +import com.whisk.docker.impl.dockerjava.DockerKitDockerJava +import com.whisk.docker.scalatest.DockerTestKit +import com.whisk.docker.{DockerContainer, DockerKit, DockerReadyChecker} +import org.apache.commons.lang.RandomStringUtils +import org.scalatest.Suite +import org.scalatest.concurrent.ScalaFutures +import org.scalatest.time.{Milliseconds, Seconds, Span} + + +trait RedisDockerCluster extends RedisContainer { + that: Suite => + + protected def redisContainerPort(container: DockerContainer): Int = container.getPorts().futureValue.apply(redisPort) + + protected lazy val runningContainers: List[DockerContainer] = (0 until 4) + .map(i => createContainer()) + .toList + + abstract override def dockerContainers: List[DockerContainer] = + runningContainers ++ super.dockerContainers + +} + +trait RedisDocker extends RedisContainer { + that: Suite => + + protected lazy val redisContainerPort: Int = runningContainer.getPorts().futureValue.apply(redisPort) + + private lazy val runningContainer = createContainer() + + abstract override def dockerContainers: List[DockerContainer] = + runningContainer :: super.dockerContainers + +} + +trait RedisContainer extends DockerKit with DockerTestKit with DockerKitDockerJava with ScalaFutures { + that: Suite => + + implicit val pc: PatienceConfig = PatienceConfig(Span(30, Seconds), Span(100, Milliseconds)) + + protected val redisContainerHost: String = "localhost" + protected val redisPort: Int = 6379 + + protected def createContainer(): DockerContainer = + DockerContainer("redis:latest", name = Some(RandomStringUtils.randomAlphabetic(10))) + .withPorts(redisPort -> None) + .withReadyChecker(DockerReadyChecker.LogLineContains("Ready to accept connections")) +} diff --git a/src/test/scala/com/redis/common/StringTypeData.scala b/src/test/scala/com/redis/common/StringTypeData.scala index 9b0fa751..300c1795 100644 --- a/src/test/scala/com/redis/common/StringTypeData.scala +++ b/src/test/scala/com/redis/common/StringTypeData.scala @@ -7,7 +7,7 @@ trait StringTypeData extends IntSpec with Matchers with GivenWhenThen { that: Suite with Informing => // StringApi, so we could put some data to test - override val r: BaseApi with StringApi with AutoCloseable + override protected def r: BaseApi with StringApi with AutoCloseable protected val testData: Map[String, String] = Map( "key1" -> "value1", diff --git a/src/test/scala/com/redis/BlockingDequeSpec.scala b/src/test/scala/com/redis/ds/BlockingDequeSpec.scala similarity index 81% rename from src/test/scala/com/redis/BlockingDequeSpec.scala rename to src/test/scala/com/redis/ds/BlockingDequeSpec.scala index c5aa2485..59366a4e 100644 --- a/src/test/scala/com/redis/BlockingDequeSpec.scala +++ b/src/test/scala/com/redis/ds/BlockingDequeSpec.scala @@ -1,13 +1,12 @@ package com.redis.ds import com.redis.RedisCommand -import org.scalatest.concurrent.ScalaFutures +import com.redis.common.RedisDocker import org.scalatest.{BeforeAndAfterAll, BeforeAndAfterEach, FunSpec, Matchers} -import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future -class BlockingDequeSpec extends FunSpec with ScalaFutures +class BlockingDequeSpec extends FunSpec with RedisDocker with Matchers with BeforeAndAfterEach with BeforeAndAfterAll { @@ -54,6 +53,6 @@ class BlockingDequeSpec extends FunSpec with ScalaFutures } private def createClient(): BlockingDeque = - new RedisDequeClient("localhost", 6379).getDeque("btd", blocking = true, timeoutInSecs = 30) + new RedisDequeClient(redisContainerHost, redisContainerPort).getDeque("btd", blocking = true, timeoutInSecs = 30) } diff --git a/src/test/scala/com/redis/DequeSpec.scala b/src/test/scala/com/redis/ds/DequeSpec.scala similarity index 90% rename from src/test/scala/com/redis/DequeSpec.scala rename to src/test/scala/com/redis/ds/DequeSpec.scala index 259d8cd1..9b63969a 100644 --- a/src/test/scala/com/redis/DequeSpec.scala +++ b/src/test/scala/com/redis/ds/DequeSpec.scala @@ -1,5 +1,6 @@ package com.redis.ds +import com.redis.RedisCommand import com.redis.common.IntSpec import org.scalatest.{FunSpec, Matchers} @@ -9,7 +10,8 @@ class DequeSpec extends FunSpec with Matchers with IntSpec { - val r = new RedisDequeClient("localhost", 6379).getDeque("td") + override protected lazy val r: RedisDeque[String] with RedisCommand = + new RedisDequeClient(redisContainerHost, redisContainerPort).getDeque("td") describe("addFirst and check size and added element") { it("should add to the head of the deque") {