/src/test/scala/redis/RedisSpec.scala

https://github.com/stanch/rediscala · Scala · 135 lines · 100 code · 35 blank · 0 comment · 0 complexity · c77edcad9c26e7780ee17964e7d77f9e MD5 · raw file

  1. package redis
  2. import org.specs2.mutable.{SpecificationLike, Tags}
  3. import akka.util.Timeout
  4. import org.specs2.time.NoTimeConversions
  5. import akka.testkit.TestKit
  6. import org.specs2.specification.{Step, Fragments}
  7. import akka.actor.ActorSystem
  8. import java.util.concurrent.atomic.AtomicInteger
  9. import scala.sys.process.Process
  10. import scala.util.Try
  11. import scala.reflect.io.File
  12. abstract class RedisHelper extends TestKit(ActorSystem()) with SpecificationLike with Tags with NoTimeConversions {
  13. import scala.concurrent.duration._
  14. implicit val executionContext = system.dispatcher
  15. implicit val timeout = Timeout(10 seconds)
  16. val timeOut = 10 seconds
  17. val longTimeOut = 100 seconds
  18. override def map(fs: => Fragments) = {
  19. Step(setup()) ^
  20. fs ^
  21. Step({
  22. system.shutdown()
  23. cleanup()
  24. })
  25. }
  26. def setup() = {}
  27. def cleanup() = {}
  28. val redisServerCmd = "redis-server"
  29. val redisServerLogLevel = "--loglevel verbose"
  30. val redisHost = "127.0.0.1"
  31. }
  32. abstract class RedisSpec extends RedisHelper with WithRedisServerLauncher {
  33. val redis = RedisClient()
  34. }
  35. trait WithRedisServerLauncher extends RedisHelper {
  36. def withRedisServer[T](block: (Int) => T): T = {
  37. val serverPort = RedisServerHelper.portNumber.getAndIncrement()
  38. val serverProcess = Process(s"$redisServerCmd --port $serverPort $redisServerLogLevel").run()
  39. val result = Try(block(serverPort))
  40. serverProcess.destroy()
  41. result.get
  42. }
  43. }
  44. abstract class RedisStandaloneServer extends RedisHelper with WithRedisServerLauncher {
  45. import RedisServerHelper._
  46. val port = portNumber.getAndIncrement()
  47. lazy val redis = RedisClient(port = port)
  48. var server: Process = null
  49. override def setup() = {
  50. server = Process(s"$redisServerCmd --port $port $redisServerLogLevel").run()
  51. }
  52. override def cleanup() = {
  53. server.destroy()
  54. }
  55. }
  56. abstract class RedisClusterClients(val masterName: String = "mymaster") extends RedisHelper {
  57. import RedisServerHelper._
  58. val masterPort = portNumber.getAndIncrement()
  59. val slavePort = portNumber.getAndIncrement()
  60. val sentinelPorts = Seq(portNumber.getAndIncrement(),portNumber.getAndIncrement())
  61. lazy val redisClient = RedisClient(port = masterPort)
  62. lazy val sentinelClient = SentinelClient(port = sentinelPorts.head)
  63. lazy val sentinelMonitoredRedisClient =
  64. SentinelMonitoredRedisClient(master = masterName,
  65. sentinels = sentinelPorts.map((redisHost, _)))
  66. var processes: Seq[Process] = null
  67. lazy val sentinelConfPath = {
  68. val sentinelConf =
  69. s"""
  70. |sentinel monitor $masterName $redisHost $masterPort 2
  71. |sentinel down-after-milliseconds $masterName 5000
  72. |sentinel can-failover $masterName yes
  73. |sentinel parallel-syncs $masterName 1
  74. |sentinel failover-timeout $masterName 10000
  75. """.stripMargin
  76. val sentinelConfFile = File.makeTemp("rediscala-sentinel", ".conf")
  77. sentinelConfFile.writeAll(sentinelConf)
  78. sentinelConfFile.path
  79. }
  80. override def setup() = {
  81. processes =
  82. Seq(
  83. Process(s"$redisServerCmd --port $masterPort $redisServerLogLevel").run(),
  84. Process(s"$redisServerCmd --port $slavePort --slaveof $redisHost $masterPort $redisServerLogLevel").run()
  85. ) ++
  86. sentinelPorts.map(p =>
  87. Process(s"$redisServerCmd $sentinelConfPath --port $p --sentinel $redisServerLogLevel").run()
  88. )
  89. }
  90. override def cleanup() = {
  91. processes.foreach(_.destroy())
  92. }
  93. def newSentinelProcess() = {
  94. val port = portNumber.getAndIncrement()
  95. Process(s"$redisServerCmd $sentinelConfPath --port $port --sentinel $redisServerLogLevel").run()
  96. }
  97. }
  98. object RedisServerHelper {
  99. val portNumber = new AtomicInteger(10500)
  100. }