2011-10-12 22:16:35 +02:00
|
|
|
/**
|
|
|
|
|
* Copyright (C) 2009-2011 Typesafe Inc. <http://www.typesafe.com>
|
|
|
|
|
*/
|
|
|
|
|
package akka.util
|
|
|
|
|
|
|
|
|
|
import org.scalatest.matchers.MustMatchers
|
2011-10-20 20:34:14 +02:00
|
|
|
import akka.dispatch.Future
|
|
|
|
|
import akka.testkit.AkkaSpec
|
|
|
|
|
import scala.util.Random
|
2011-10-12 22:16:35 +02:00
|
|
|
|
2011-10-20 20:34:14 +02:00
|
|
|
class IndexSpec extends AkkaSpec with MustMatchers {
|
2011-10-12 22:16:35 +02:00
|
|
|
|
2011-10-20 20:34:14 +02:00
|
|
|
private def emptyIndex = new Index[String, Int](100, _ compareTo _)
|
2011-10-12 22:16:35 +02:00
|
|
|
|
|
|
|
|
private def indexWithValues = {
|
|
|
|
|
val index = emptyIndex
|
|
|
|
|
index.put("s1", 1)
|
|
|
|
|
index.put("s1", 2)
|
|
|
|
|
index.put("s1", 3)
|
|
|
|
|
index.put("s2", 1)
|
|
|
|
|
index.put("s2", 2)
|
|
|
|
|
index.put("s3", 2)
|
|
|
|
|
|
|
|
|
|
index
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"An Index" must {
|
|
|
|
|
|
|
|
|
|
"take and return a value" in {
|
|
|
|
|
val index = emptyIndex
|
|
|
|
|
index.put("s1", 1)
|
2011-10-13 13:27:07 +02:00
|
|
|
index.valueIterator("s1").toSet must be === Set(1)
|
2011-10-12 22:16:35 +02:00
|
|
|
}
|
|
|
|
|
"take and return several values" in {
|
|
|
|
|
val index = emptyIndex
|
2011-10-13 13:27:07 +02:00
|
|
|
index.put("s1", 1) must be === true
|
|
|
|
|
index.put("s1", 1) must be === false
|
2011-10-12 22:16:35 +02:00
|
|
|
index.put("s1", 2)
|
|
|
|
|
index.put("s1", 3)
|
|
|
|
|
index.put("s2", 4)
|
2011-10-13 13:27:07 +02:00
|
|
|
index.valueIterator("s1").toSet must be === Set(1, 2, 3)
|
|
|
|
|
index.valueIterator("s2").toSet must be === Set(4)
|
2011-10-12 22:16:35 +02:00
|
|
|
}
|
|
|
|
|
"remove values" in {
|
|
|
|
|
val index = emptyIndex
|
|
|
|
|
index.put("s1", 1)
|
|
|
|
|
index.put("s1", 2)
|
|
|
|
|
index.put("s2", 1)
|
|
|
|
|
index.put("s2", 2)
|
|
|
|
|
//Remove value
|
2011-10-13 13:27:07 +02:00
|
|
|
index.remove("s1", 1) must be === true
|
|
|
|
|
index.remove("s1", 1) must be === false
|
|
|
|
|
index.valueIterator("s1").toSet must be === Set(2)
|
2011-10-12 22:16:35 +02:00
|
|
|
//Remove key
|
|
|
|
|
index.remove("s2") match {
|
2011-10-13 13:27:07 +02:00
|
|
|
case Some(iter) ⇒ iter.toSet must be === Set(1, 2)
|
2011-10-12 22:16:35 +02:00
|
|
|
case None ⇒ fail()
|
|
|
|
|
}
|
2011-10-13 13:27:07 +02:00
|
|
|
index.remove("s2") must be === None
|
|
|
|
|
index.valueIterator("s2").toSet must be === Set()
|
2011-10-12 22:16:35 +02:00
|
|
|
}
|
|
|
|
|
"remove the specified value" in {
|
|
|
|
|
val index = emptyIndex
|
|
|
|
|
index.put("s1", 1)
|
|
|
|
|
index.put("s1", 2)
|
|
|
|
|
index.put("s1", 3)
|
|
|
|
|
index.put("s2", 1)
|
|
|
|
|
index.put("s2", 2)
|
|
|
|
|
index.put("s3", 2)
|
|
|
|
|
|
|
|
|
|
index.removeValue(1)
|
2011-10-13 13:27:07 +02:00
|
|
|
index.valueIterator("s1").toSet must be === Set(2, 3)
|
|
|
|
|
index.valueIterator("s2").toSet must be === Set(2)
|
|
|
|
|
index.valueIterator("s3").toSet must be === Set(2)
|
2011-10-12 22:16:35 +02:00
|
|
|
}
|
|
|
|
|
"apply a function for all key-value pairs and find every value" in {
|
|
|
|
|
val index = indexWithValues
|
|
|
|
|
|
|
|
|
|
var valueCount = 0
|
|
|
|
|
index.foreach((key, value) ⇒ {
|
|
|
|
|
valueCount = valueCount + 1
|
2011-10-13 13:27:07 +02:00
|
|
|
index.findValue(key)(_ == value) must be === Some(value)
|
2011-10-12 22:16:35 +02:00
|
|
|
})
|
2011-10-13 13:27:07 +02:00
|
|
|
valueCount must be === 6
|
2011-10-12 22:16:35 +02:00
|
|
|
}
|
|
|
|
|
"be cleared" in {
|
|
|
|
|
val index = indexWithValues
|
2011-10-13 13:27:07 +02:00
|
|
|
index.isEmpty must be === false
|
2011-10-12 22:16:35 +02:00
|
|
|
index.clear()
|
2011-10-13 13:27:07 +02:00
|
|
|
index.isEmpty must be === true
|
|
|
|
|
}
|
|
|
|
|
"be able to be accessed in parallel" in {
|
2011-10-20 20:34:14 +02:00
|
|
|
val index = new Index[Int, Int](100, _ compareTo _)
|
|
|
|
|
val nrOfTasks = 10000
|
|
|
|
|
val nrOfKeys = 10
|
|
|
|
|
val nrOfValues = 10
|
|
|
|
|
//Fill index
|
|
|
|
|
for (key ← 0 until nrOfKeys; value ← 0 until nrOfValues)
|
2011-10-13 13:27:07 +02:00
|
|
|
index.put(key, value)
|
2011-10-20 20:34:14 +02:00
|
|
|
//Tasks to be executed in parallel
|
|
|
|
|
def putTask() = Future {
|
|
|
|
|
index.put(Random.nextInt(nrOfKeys), Random.nextInt(nrOfValues))
|
|
|
|
|
}
|
|
|
|
|
def removeTask1() = Future {
|
|
|
|
|
index.remove(Random.nextInt(nrOfKeys / 2), Random.nextInt(nrOfValues))
|
|
|
|
|
}
|
|
|
|
|
def removeTask2() = Future {
|
|
|
|
|
index.remove(Random.nextInt(nrOfKeys / 2))
|
|
|
|
|
}
|
|
|
|
|
def readTask() = Future {
|
|
|
|
|
val key = Random.nextInt(nrOfKeys)
|
|
|
|
|
val values = index.valueIterator(key)
|
|
|
|
|
if (key >= nrOfKeys / 2) {
|
|
|
|
|
values.isEmpty must be === false
|
2011-10-13 13:27:07 +02:00
|
|
|
}
|
|
|
|
|
}
|
2011-10-20 20:34:14 +02:00
|
|
|
|
|
|
|
|
def executeRandomTask() = Random.nextInt(4) match {
|
|
|
|
|
case 0 ⇒ putTask()
|
|
|
|
|
case 1 ⇒ removeTask1()
|
|
|
|
|
case 2 ⇒ removeTask2()
|
|
|
|
|
case 3 ⇒ readTask()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val tasks = List.fill(nrOfTasks)(executeRandomTask)
|
|
|
|
|
|
|
|
|
|
tasks.foreach(_.await)
|
|
|
|
|
tasks.foreach(_.exception.map(throw _))
|
2011-10-12 22:16:35 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|