diff --git a/embedded-repo/dispatch/http/dispatch-http/0.5.2/dispatch-http-0.5.2.jar b/embedded-repo/dispatch/http/dispatch-http/0.5.2/dispatch-http-0.5.2.jar new file mode 100644 index 0000000000..c313e7cb8a Binary files /dev/null and b/embedded-repo/dispatch/http/dispatch-http/0.5.2/dispatch-http-0.5.2.jar differ diff --git a/embedded-repo/dispatch/json/dispatch-json/0.5.2/dispatch-json-0.5.2.jar b/embedded-repo/dispatch/json/dispatch-json/0.5.2/dispatch-json-0.5.2.jar new file mode 100644 index 0000000000..596c9851ec Binary files /dev/null and b/embedded-repo/dispatch/json/dispatch-json/0.5.2/dispatch-json-0.5.2.jar differ diff --git a/embedded-repo/sjson/json/sjson/0.1/sjson-0.1.jar b/embedded-repo/sjson/json/sjson/0.1/sjson-0.1.jar new file mode 100644 index 0000000000..9d3e3733d5 Binary files /dev/null and b/embedded-repo/sjson/json/sjson/0.1/sjson-0.1.jar differ diff --git a/kernel/pom.xml b/kernel/pom.xml index 41c3fc05f3..4af5fc8d66 100644 --- a/kernel/pom.xml +++ b/kernel/pom.xml @@ -1,274 +1,290 @@ - - 4.0.0 - - akka-kernel - Akka Kernel Module - - jar - - - akka - se.scalablesolutions.akka - 0.6 - ../pom.xml - - - - - - akka-util-java - se.scalablesolutions.akka - 0.6 - - - org.scala-lang - scala-library - 2.7.5 - - - org.codehaus.aspectwerkz - aspectwerkz-nodeps-jdk5 - 2.1 - - - org.codehaus.aspectwerkz - aspectwerkz-jdk5 - 2.1 - - - com.twitter - scala-stats - 1.0 - - - net.lag - configgy - 1.3 - - - org.guiceyfruit - guice-core - 2.0-beta-4 - - - org.apache.camel - camel-core - 2.0-SNAPSHOT - - - org.jboss.netty - netty - 3.1.0.GA - - - org.apache - zookeeper - 3.1.0 - - - org.scala-tools - javautils - 2.7.4-0.1 - - - - - org.codehaus.jackson - jackson-core-asl - 1.1.0 - - - org.codehaus.jackson - jackson-mapper-asl - 1.1.0 - - - com.google.protobuf - protobuf-java - 2.1.0 - - - sbinary - sbinary - 0.3 - - - com.twitter - scala-json - 1.0 - - - - - com.mongodb - mongo - 0.6 - - - - - org.apache.cassandra - cassandra - 0.4.0-trunk - - - com.facebook - thrift - 1.0 - - - com.facebook - fb303 - 1.0 - - - commons-pool - commons-pool - 1.5.1 - - - - - com.sun.grizzly - grizzly-comet-webserver - 1.8.6.3 - - - com.sun.jersey - jersey-server - 1.1.1-ea - - - com.sun.jersey - jersey-json - 1.1.1-ea - - - javax.ws.rs - jsr311-api - 1.0 - - - com.sun.jersey.contribs - jersey-scala - 1.1.2-ea-SNAPSHOT - - - org.atmosphere - atmosphere-core - 0.3 - - - org.atmosphere - atmosphere-portable-runtime - 0.3 - - - org.atmosphere - atmosphere-compat - 0.3 - - - - - org.slf4j - slf4j-log4j12 - 1.4.3 - - - org.slf4j - slf4j-api - 1.4.3 - - - log4j - log4j - 1.2.13 - - - commons-logging - commons-logging - 1.0.4 - - - - - org.scala-tools.testing - scalatest - 0.9.5 - test - - - junit - junit - 4.5 - test - - - - - - - maven-assembly-plugin - 2.2-beta-2 - - - create-executable-jar - install - - single - - - - - jar-with-dependencies - - - - - se.scalablesolutions.akka.kernel.Kernel - - - - - - - - maven-antrun-plugin - - - install - - - - - - - run - - - - - - - - false - ../config - - akka.conf - akka-reference.conf - - - - false - src/main/resources - - META-INF/* - - - - - + + 4.0.0 + + akka-kernel + Akka Kernel Module + + jar + + + akka + se.scalablesolutions.akka + 0.6 + ../pom.xml + + + + + + akka-util-java + se.scalablesolutions.akka + 0.6 + + + org.scala-lang + scala-library + 2.7.5 + + + org.codehaus.aspectwerkz + aspectwerkz-nodeps-jdk5 + 2.1 + + + org.codehaus.aspectwerkz + aspectwerkz-jdk5 + 2.1 + + + com.twitter + scala-stats + 1.0 + + + net.lag + configgy + 1.3 + + + org.guiceyfruit + guice-core + 2.0-beta-4 + + + org.apache.camel + camel-core + 2.0-SNAPSHOT + + + org.jboss.netty + netty + 3.1.0.GA + + + org.apache + zookeeper + 3.1.0 + + + org.scala-tools + javautils + 2.7.4-0.1 + + + + + org.codehaus.jackson + jackson-core-asl + 1.1.0 + + + org.codehaus.jackson + jackson-mapper-asl + 1.1.0 + + + com.google.protobuf + protobuf-java + 2.1.0 + + + sbinary + sbinary + 0.3 + + + com.twitter + scala-json + 1.0 + + + dispatch.json + dispatch-json + 0.5.2 + + + dispatch.http + dispatch-http + 0.5.2 + + + sjson.json + sjson + 0.1 + + + + + + com.mongodb + mongo + 0.6 + + + + + org.apache.cassandra + cassandra + 0.4.0-trunk + + + com.facebook + thrift + 1.0 + + + com.facebook + fb303 + 1.0 + + + commons-pool + commons-pool + 1.5.1 + + + + + com.sun.grizzly + grizzly-comet-webserver + 1.8.6.3 + + + com.sun.jersey + jersey-server + 1.1.1-ea + + + com.sun.jersey + jersey-json + 1.1.1-ea + + + javax.ws.rs + jsr311-api + 1.0 + + + com.sun.jersey.contribs + jersey-scala + 1.1.2-ea-SNAPSHOT + + + org.atmosphere + atmosphere-core + 0.3 + + + org.atmosphere + atmosphere-portable-runtime + 0.3 + + + org.atmosphere + atmosphere-compat + 0.3 + + + + + org.slf4j + slf4j-log4j12 + 1.4.3 + + + org.slf4j + slf4j-api + 1.4.3 + + + log4j + log4j + 1.2.13 + + + commons-logging + commons-logging + 1.0.4 + + + + + org.scala-tools.testing + scalatest + 0.9.5 + test + + + junit + junit + 4.5 + test + + + + + + + maven-assembly-plugin + 2.2-beta-2 + + + create-executable-jar + install + + single + + + + + jar-with-dependencies + + + + + se.scalablesolutions.akka.kernel.Kernel + + + + + + + + maven-antrun-plugin + + + install + + + + + + + run + + + + + + + + false + ../config + + akka.conf + akka-reference.conf + + + + false + src/main/resources + + META-INF/* + + + + + diff --git a/kernel/src/main/scala/state/MongoStorage.scala b/kernel/src/main/scala/state/MongoStorage.scala index f72e1c7771..bfb2e1dd49 100644 --- a/kernel/src/main/scala/state/MongoStorage.scala +++ b/kernel/src/main/scala/state/MongoStorage.scala @@ -1,291 +1,290 @@ -package se.scalablesolutions.akka.kernel.state - -import com.mongodb._ -import se.scalablesolutions.akka.kernel.util.Logging -import serialization.{Serializer} -import kernel.Kernel.config - -import java.util.{Map=>JMap, List=>JList, ArrayList=>JArrayList} - -/** - * A module for supporting MongoDB based persistence. - *

- * The module offers functionality for: - *

  • Persistent Maps
  • - *
  • Persistent Vectors
  • - *
  • Persistent Refs
  • - *

    - * @author Debasish Ghosh - */ -object MongoStorage extends MapStorage - with VectorStorage with RefStorage with Logging { - - // enrich with null safe findOne - class RichDBCollection(value: DBCollection) { - def findOneNS(o: DBObject): Option[DBObject] = { - value.findOne(o) match { - case null => None - case x => Some(x) - } - } - } - - implicit def enrichDBCollection(c: DBCollection) = new RichDBCollection(c) - - val KEY = "key" - val VALUE = "value" - val COLLECTION = "akka_coll" - val MONGODB_SERVER_HOSTNAME = - config.getString("akka.storage.mongodb.hostname", "127.0.0.1") - val MONGODB_SERVER_DBNAME = - config.getString("akka.storage.mongodb.dbname", "testdb") - val MONGODB_SERVER_PORT = - config.getInt("akka.storage.mongodb.port", 27017) - - val db = new Mongo(MONGODB_SERVER_HOSTNAME, - MONGODB_SERVER_PORT, MONGODB_SERVER_DBNAME) - val coll = db.getCollection(COLLECTION) - - // @fixme: make this pluggable - private[this] val serializer: Serializer = Serializer.ScalaJSON - - override def insertMapStorageEntryFor(name: String, - key: AnyRef, value: AnyRef) { - insertMapStorageEntriesFor(name, List((key, value))) - } - - override def insertMapStorageEntriesFor(name: String, - entries: List[Tuple2[AnyRef, AnyRef]]) { - import java.util.{Map, HashMap} - - val m: Map[AnyRef, AnyRef] = new HashMap - for ((k, v) <- entries) { - m.put(k, serializer.out(v)) - } - - nullSafeFindOne(name) match { - case None => - coll.insert(new BasicDBObject().append(KEY, name).append(VALUE, m)) - case Some(dbo) => { - // collate the maps - val o = dbo.get(VALUE).asInstanceOf[Map[AnyRef, AnyRef]] - o.putAll(m) - - // remove existing reference - removeMapStorageFor(name) - // and insert - coll.insert(new BasicDBObject().append(KEY, name).append(VALUE, o)) - } - } - } - - override def removeMapStorageFor(name: String) = { - val q = new BasicDBObject - q.put(KEY, name) - coll.remove(q) - } - - override def removeMapStorageFor(name: String, key: AnyRef) = { - nullSafeFindOne(name) match { - case None => - case Some(dbo) => { - val orig = dbo.get(VALUE).asInstanceOf[DBObject].toMap - orig.remove(key.asInstanceOf[String]) - - // remove existing reference - removeMapStorageFor(name) - // and insert - coll.insert(new BasicDBObject().append(KEY, name).append(VALUE, orig)) - } - } - } - - override def getMapStorageEntryFor(name: String, - key: AnyRef): Option[AnyRef] = { - getValueForKey(name, key.asInstanceOf[String]) - } - - override def getMapStorageSizeFor(name: String): Int = { - nullSafeFindOne(name) match { - case None => 0 - case Some(dbo) => - dbo.get(VALUE).asInstanceOf[JMap[String, AnyRef]].keySet.size - } - } - - override def getMapStorageFor(name: String): List[Tuple2[AnyRef, AnyRef]] = { - val m = - nullSafeFindOne(name) match { - case None => - throw new Predef.NoSuchElementException(name + " not present") - case Some(dbo) => - dbo.get(VALUE).asInstanceOf[JMap[String, AnyRef]] - } - val n = - List(m.keySet.toArray: _*).asInstanceOf[List[String]] - val vals = - for(s <- n) - yield (s, serializer.in(m.get(s).asInstanceOf[Array[Byte]], None)) - vals.asInstanceOf[List[Tuple2[String, AnyRef]]] - } - - override def getMapStorageRangeFor(name: String, start: Option[AnyRef], - finish: Option[AnyRef], - count: Int): List[Tuple2[AnyRef, AnyRef]] = { - val m = - nullSafeFindOne(name) match { - case None => - throw new Predef.NoSuchElementException(name + " not present") - case Some(dbo) => - dbo.get(VALUE).asInstanceOf[JMap[String, AnyRef]] - } - - /** - * count is the max number of results to return. Start with - * start or 0 (if start is not defined) and go until - * you hit finish or count. - */ - val s = if (start.isDefined) start.get.asInstanceOf[Int] else 0 - val cnt = - if (finish.isDefined) { - val f = finish.get.asInstanceOf[Int] - if (f >= s) Math.min(count, (f - s)) else count - } - else count - - val n = - List(m.keySet.toArray: _*).asInstanceOf[List[String]].sort((e1, e2) => (e1 compareTo e2) < 0).slice(s, s + cnt) - val vals = - for(s <- n) - yield (s, serializer.in(m.get(s).asInstanceOf[Array[Byte]], None)) - vals.asInstanceOf[List[Tuple2[String, AnyRef]]] - } - - private def getValueForKey(name: String, key: String): Option[AnyRef] = { - try { - nullSafeFindOne(name) match { - case None => None - case Some(dbo) => - Some(serializer.in( - dbo.get(VALUE) - .asInstanceOf[JMap[String, AnyRef]] - .get(key).asInstanceOf[Array[Byte]], None)) - } - } catch { - case e => - throw new Predef.NoSuchElementException(e.getMessage) - } - } - - override def insertVectorStorageEntriesFor(name: String, elements: List[AnyRef]) = { - val q = new BasicDBObject - q.put(KEY, name) - - val currentList = - coll.findOneNS(q) match { - case None => - new JArrayList[AnyRef] - case Some(dbo) => - dbo.get(VALUE).asInstanceOf[JArrayList[AnyRef]] - } - if (!currentList.isEmpty) { - // record exists - // remove before adding - coll.remove(q) - } - - // add to the current list - elements.map(serializer.out(_)).foreach(currentList.add(_)) - - coll.insert( - new BasicDBObject() - .append(KEY, name) - .append(VALUE, currentList) - ) - } - - override def insertVectorStorageEntryFor(name: String, element: AnyRef) = { - insertVectorStorageEntriesFor(name, List(element)) - } - - override def getVectorStorageEntryFor(name: String, index: Int): AnyRef = { - try { - val o = - nullSafeFindOne(name) match { - case None => - throw new Predef.NoSuchElementException(name + " not present") - - case Some(dbo) => - dbo.get(VALUE).asInstanceOf[JList[AnyRef]] - } - serializer.in( - o.get(index).asInstanceOf[Array[Byte]], - None - ) - } catch { - case e => - throw new Predef.NoSuchElementException(e.getMessage) - } - } - - override def getVectorStorageRangeFor(name: String, - start: Option[Int], finish: Option[Int], count: Int): List[AnyRef] = { - try { - val o = - nullSafeFindOne(name) match { - case None => - throw new Predef.NoSuchElementException(name + " not present") - - case Some(dbo) => - dbo.get(VALUE).asInstanceOf[JList[AnyRef]] - } - - // pick the subrange and make a Scala list - val l = - List(o.subList(start.get, start.get + count).toArray: _*) - - for(e <- l) - yield serializer.in(e.asInstanceOf[Array[Byte]], None) - } catch { - case e => - throw new Predef.NoSuchElementException(e.getMessage) - } - } - - override def getVectorStorageSizeFor(name: String): Int = { - nullSafeFindOne(name) match { - case None => 0 - case Some(dbo) => - dbo.get(VALUE).asInstanceOf[JList[AnyRef]].size - } - } - - private def nullSafeFindOne(name: String): Option[DBObject] = { - val o = new BasicDBObject - o.put(KEY, name) - coll.findOneNS(o) - } - - override def insertRefStorageFor(name: String, element: AnyRef) = { - nullSafeFindOne(name) match { - case None => - case Some(dbo) => { - val q = new BasicDBObject - q.put(KEY, name) - coll.remove(q) - } - } - coll.insert( - new BasicDBObject() - .append(KEY, name) - .append(VALUE, serializer.out(element))) - } - - override def getRefStorageFor(name: String): Option[AnyRef] = { - nullSafeFindOne(name) match { - case None => None - case Some(dbo) => - Some(serializer.in(dbo.get(VALUE).asInstanceOf[Array[Byte]], None)) - } - } -} +package se.scalablesolutions.akka.kernel.state + +import com.mongodb._ +import se.scalablesolutions.akka.kernel.util.Logging +import serialization.{Serializer} +import kernel.Kernel.config +import sjson.json.Serializer._ + +import java.util.{Map=>JMap, List=>JList, ArrayList=>JArrayList} + +/** + * A module for supporting MongoDB based persistence. + *

    + * The module offers functionality for: + *

  • Persistent Maps
  • + *
  • Persistent Vectors
  • + *
  • Persistent Refs
  • + *

    + * @author Debasish Ghosh + */ +object MongoStorage extends MapStorage + with VectorStorage with RefStorage with Logging { + + // enrich with null safe findOne + class RichDBCollection(value: DBCollection) { + def findOneNS(o: DBObject): Option[DBObject] = { + value.findOne(o) match { + case null => None + case x => Some(x) + } + } + } + + implicit def enrichDBCollection(c: DBCollection) = new RichDBCollection(c) + + val KEY = "key" + val VALUE = "value" + val COLLECTION = "akka_coll" + val MONGODB_SERVER_HOSTNAME = + config.getString("akka.storage.mongodb.hostname", "127.0.0.1") + val MONGODB_SERVER_DBNAME = + config.getString("akka.storage.mongodb.dbname", "testdb") + val MONGODB_SERVER_PORT = + config.getInt("akka.storage.mongodb.port", 27017) + + val db = new Mongo(MONGODB_SERVER_HOSTNAME, + MONGODB_SERVER_PORT, MONGODB_SERVER_DBNAME) + val coll = db.getCollection(COLLECTION) + + // @fixme: make this pluggable + private[this] val serializer = SJSON + + override def insertMapStorageEntryFor(name: String, + key: AnyRef, value: AnyRef) { + insertMapStorageEntriesFor(name, List((key, value))) + } + + override def insertMapStorageEntriesFor(name: String, + entries: List[Tuple2[AnyRef, AnyRef]]) { + import java.util.{Map, HashMap} + + val m: Map[AnyRef, AnyRef] = new HashMap + for ((k, v) <- entries) { + m.put(k, serializer.out(v)) + } + + nullSafeFindOne(name) match { + case None => + coll.insert(new BasicDBObject().append(KEY, name).append(VALUE, m)) + case Some(dbo) => { + // collate the maps + val o = dbo.get(VALUE).asInstanceOf[Map[AnyRef, AnyRef]] + o.putAll(m) + + // remove existing reference + removeMapStorageFor(name) + // and insert + coll.insert(new BasicDBObject().append(KEY, name).append(VALUE, o)) + } + } + } + + override def removeMapStorageFor(name: String) = { + val q = new BasicDBObject + q.put(KEY, name) + coll.remove(q) + } + + override def removeMapStorageFor(name: String, key: AnyRef) = { + nullSafeFindOne(name) match { + case None => + case Some(dbo) => { + val orig = dbo.get(VALUE).asInstanceOf[DBObject].toMap + orig.remove(key.asInstanceOf[String]) + + // remove existing reference + removeMapStorageFor(name) + // and insert + coll.insert(new BasicDBObject().append(KEY, name).append(VALUE, orig)) + } + } + } + + override def getMapStorageEntryFor(name: String, + key: AnyRef): Option[AnyRef] = { + getValueForKey(name, key.asInstanceOf[String]) + } + + override def getMapStorageSizeFor(name: String): Int = { + nullSafeFindOne(name) match { + case None => 0 + case Some(dbo) => + dbo.get(VALUE).asInstanceOf[JMap[String, AnyRef]].keySet.size + } + } + + override def getMapStorageFor(name: String): List[Tuple2[AnyRef, AnyRef]] = { + val m = + nullSafeFindOne(name) match { + case None => + throw new Predef.NoSuchElementException(name + " not present") + case Some(dbo) => + dbo.get(VALUE).asInstanceOf[JMap[String, AnyRef]] + } + val n = + List(m.keySet.toArray: _*).asInstanceOf[List[String]] + val vals = + for(s <- n) + yield (s, serializer.in[AnyRef](m.get(s).asInstanceOf[Array[Byte]])) + vals.asInstanceOf[List[Tuple2[String, AnyRef]]] + } + + override def getMapStorageRangeFor(name: String, start: Option[AnyRef], + finish: Option[AnyRef], + count: Int): List[Tuple2[AnyRef, AnyRef]] = { + val m = + nullSafeFindOne(name) match { + case None => + throw new Predef.NoSuchElementException(name + " not present") + case Some(dbo) => + dbo.get(VALUE).asInstanceOf[JMap[String, AnyRef]] + } + + /** + * count is the max number of results to return. Start with + * start or 0 (if start is not defined) and go until + * you hit finish or count. + */ + val s = if (start.isDefined) start.get.asInstanceOf[Int] else 0 + val cnt = + if (finish.isDefined) { + val f = finish.get.asInstanceOf[Int] + if (f >= s) Math.min(count, (f - s)) else count + } + else count + + val n = + List(m.keySet.toArray: _*).asInstanceOf[List[String]].sort((e1, e2) => (e1 compareTo e2) < 0).slice(s, s + cnt) + val vals = + for(s <- n) + yield (s, serializer.in[AnyRef](m.get(s).asInstanceOf[Array[Byte]])) + vals.asInstanceOf[List[Tuple2[String, AnyRef]]] + } + + private def getValueForKey(name: String, key: String): Option[AnyRef] = { + try { + nullSafeFindOne(name) match { + case None => None + case Some(dbo) => + Some(serializer.in[AnyRef]( + dbo.get(VALUE) + .asInstanceOf[JMap[String, AnyRef]] + .get(key).asInstanceOf[Array[Byte]])) + } + } catch { + case e => + throw new Predef.NoSuchElementException(e.getMessage) + } + } + + override def insertVectorStorageEntriesFor(name: String, elements: List[AnyRef]) = { + val q = new BasicDBObject + q.put(KEY, name) + + val currentList = + coll.findOneNS(q) match { + case None => + new JArrayList[AnyRef] + case Some(dbo) => + dbo.get(VALUE).asInstanceOf[JArrayList[AnyRef]] + } + if (!currentList.isEmpty) { + // record exists + // remove before adding + coll.remove(q) + } + + // add to the current list + elements.map(serializer.out(_)).foreach(currentList.add(_)) + + coll.insert( + new BasicDBObject() + .append(KEY, name) + .append(VALUE, currentList) + ) + } + + override def insertVectorStorageEntryFor(name: String, element: AnyRef) = { + insertVectorStorageEntriesFor(name, List(element)) + } + + override def getVectorStorageEntryFor(name: String, index: Int): AnyRef = { + try { + val o = + nullSafeFindOne(name) match { + case None => + throw new Predef.NoSuchElementException(name + " not present") + + case Some(dbo) => + dbo.get(VALUE).asInstanceOf[JList[AnyRef]] + } + serializer.in[AnyRef]( + o.get(index).asInstanceOf[Array[Byte]]) + } catch { + case e => + throw new Predef.NoSuchElementException(e.getMessage) + } + } + + override def getVectorStorageRangeFor(name: String, + start: Option[Int], finish: Option[Int], count: Int): List[AnyRef] = { + try { + val o = + nullSafeFindOne(name) match { + case None => + throw new Predef.NoSuchElementException(name + " not present") + + case Some(dbo) => + dbo.get(VALUE).asInstanceOf[JList[AnyRef]] + } + + // pick the subrange and make a Scala list + val l = + List(o.subList(start.get, start.get + count).toArray: _*) + + for(e <- l) + yield serializer.in[AnyRef](e.asInstanceOf[Array[Byte]]) + } catch { + case e => + throw new Predef.NoSuchElementException(e.getMessage) + } + } + + override def getVectorStorageSizeFor(name: String): Int = { + nullSafeFindOne(name) match { + case None => 0 + case Some(dbo) => + dbo.get(VALUE).asInstanceOf[JList[AnyRef]].size + } + } + + private def nullSafeFindOne(name: String): Option[DBObject] = { + val o = new BasicDBObject + o.put(KEY, name) + coll.findOneNS(o) + } + + override def insertRefStorageFor(name: String, element: AnyRef) = { + nullSafeFindOne(name) match { + case None => + case Some(dbo) => { + val q = new BasicDBObject + q.put(KEY, name) + coll.remove(q) + } + } + coll.insert( + new BasicDBObject() + .append(KEY, name) + .append(VALUE, serializer.out(element))) + } + + override def getRefStorageFor(name: String): Option[AnyRef] = { + nullSafeFindOne(name) match { + case None => None + case Some(dbo) => + Some(serializer.in[AnyRef](dbo.get(VALUE).asInstanceOf[Array[Byte]])) + } + } +} diff --git a/kernel/src/test/scala/MongoPersistentActorSpec.scala b/kernel/src/test/scala/MongoPersistentActorSpec.scala index eb5e04c85e..be0b1c320c 100644 --- a/kernel/src/test/scala/MongoPersistentActorSpec.scala +++ b/kernel/src/test/scala/MongoPersistentActorSpec.scala @@ -4,6 +4,8 @@ package se.scalablesolutions.akka.kernel.actor import junit.framework.TestCase import org.junit.{Test, Before} import org.junit.Assert._ +import dispatch.json._ +import dispatch.json.Js._ import kernel.state.{MongoStorageConfig, TransactionalState} @@ -45,7 +47,10 @@ class BankAccountActor extends Actor { val m: BigInt = accountState.get(accountNo) match { case None => 0 - case Some(v) => BigInt(v.asInstanceOf[String]) + case Some(v) => { + val JsNumber(n) = v.asInstanceOf[JsValue] + BigInt(n.toString) + } } accountState.put(accountNo, (m - amount)) if (amount > m) @@ -75,7 +80,10 @@ class BankAccountActor extends Actor { val m: BigInt = accountState.get(accountNo) match { case None => 0 - case Some(v) => BigInt(v.asInstanceOf[String]) + case Some(v) => { + val JsNumber(n) = v.asInstanceOf[JsValue] + BigInt(n.toString) + } } accountState.put(accountNo, (m + amount)) reply(m + amount) @@ -84,14 +92,6 @@ class BankAccountActor extends Actor { reply(txnLog.length.asInstanceOf[AnyRef]) } } -/* -@serializable class PersistentFailerActor extends Actor { - makeTransactionRequired - def receive: PartialFunction[Any, Unit] = { - case "Failure" => - throw new RuntimeException("expected") - } -}*/ class MongoPersistentActorSpec extends TestCase { @Test @@ -102,16 +102,19 @@ class MongoPersistentActorSpec extends TestCase { failer.start bactor !! Credit("a-123", 5000) bactor !! Debit("a-123", 3000, failer) - assertEquals(BigInt(2000), - BigInt((bactor !! Balance("a-123")).get.asInstanceOf[String])) + val b = (bactor !! Balance("a-123")).get.asInstanceOf[JsValue] + val JsNumber(n) = b + assertEquals(BigInt(2000), BigInt(n.toString)) bactor !! Credit("a-123", 7000) - assertEquals(BigInt(9000), - BigInt((bactor !! Balance("a-123")).get.asInstanceOf[String])) + val b1 = (bactor !! Balance("a-123")).get.asInstanceOf[JsValue] + val JsNumber(n1) = b1 + assertEquals(BigInt(9000), BigInt(n1.toString)) bactor !! Debit("a-123", 8000, failer) - assertEquals(BigInt(1000), - BigInt((bactor !! Balance("a-123")).get.asInstanceOf[String])) + val b2 = (bactor !! Balance("a-123")).get.asInstanceOf[JsValue] + val JsNumber(n2) = b2 + assertEquals(BigInt(1000), BigInt(n2.toString)) assertEquals(7, (bactor !! LogSize).get) } @@ -120,8 +123,10 @@ class MongoPersistentActorSpec extends TestCase { val bactor = new BankAccountActor bactor.start bactor !! Credit("a-123", 5000) - assertEquals(BigInt(5000), - BigInt((bactor !! Balance("a-123")).get.asInstanceOf[String])) + + val b = (bactor !! Balance("a-123")).get.asInstanceOf[JsValue] + val JsNumber(n) = b + assertEquals(BigInt(5000), BigInt(n.toString)) val failer = new PersistentFailerActor failer.start @@ -130,8 +135,9 @@ class MongoPersistentActorSpec extends TestCase { fail("should throw exception") } catch { case e: RuntimeException => {}} - assertEquals(BigInt(5000), - BigInt((bactor !! Balance("a-123")).get.asInstanceOf[String])) + val b1 = (bactor !! Balance("a-123")).get.asInstanceOf[JsValue] + val JsNumber(n1) = b1 + assertEquals(BigInt(5000), BigInt(n1.toString)) // should not count the failed one assertEquals(3, (bactor !! LogSize).get) @@ -142,8 +148,9 @@ class MongoPersistentActorSpec extends TestCase { val bactor = new BankAccountActor bactor.start bactor !! Credit("a-123", 5000) - assertEquals(BigInt(5000), - BigInt((bactor !! Balance("a-123")).get.asInstanceOf[String])) + val b = (bactor !! Balance("a-123")).get.asInstanceOf[JsValue] + val JsNumber(n) = b + assertEquals(BigInt(5000), BigInt(n.toString)) val failer = new PersistentFailerActor failer.start @@ -152,8 +159,9 @@ class MongoPersistentActorSpec extends TestCase { fail("should throw exception") } catch { case e: RuntimeException => {}} - assertEquals(BigInt(5000), - BigInt((bactor !! Balance("a-123")).get.asInstanceOf[String])) + val b1 = (bactor !! Balance("a-123")).get.asInstanceOf[JsValue] + val JsNumber(n1) = b1 + assertEquals(BigInt(5000), BigInt(n1.toString)) // should not count the failed one assertEquals(3, (bactor !! LogSize).get) diff --git a/kernel/src/test/scala/MongoStorageSpec.scala b/kernel/src/test/scala/MongoStorageSpec.scala index c80afb00a7..07f7a21bf0 100644 --- a/kernel/src/test/scala/MongoStorageSpec.scala +++ b/kernel/src/test/scala/MongoStorageSpec.scala @@ -1,306 +1,337 @@ -package se.scalablesolutions.akka.kernel.state - -import junit.framework.TestCase - -import org.junit.{Test, Before} -import org.junit.Assert._ - -class MongoStorageSpec extends TestCase { - - val changeSetV = new scala.collection.mutable.ArrayBuffer[AnyRef] - val changeSetM = new scala.collection.mutable.HashMap[AnyRef, AnyRef] - - override def setUp = { - MongoStorage.coll.drop - } - - @Test - def testVectorInsertForTransactionId = { - changeSetV += "debasish" // string - changeSetV += List(1, 2, 3) // Scala List - changeSetV += List(100, 200) - MongoStorage.insertVectorStorageEntriesFor("U-A1", changeSetV.toList) - assertEquals( - 3, - MongoStorage.getVectorStorageSizeFor("U-A1")) - changeSetV.clear - - // changeSetV should be reinitialized - changeSetV += List(12, 23, 45) - changeSetV += "maulindu" - MongoStorage.insertVectorStorageEntriesFor("U-A1", changeSetV.toList) - assertEquals( - 5, - MongoStorage.getVectorStorageSizeFor("U-A1")) - - // add more to the same changeSetV - changeSetV += "ramanendu" - changeSetV += Map(1 -> "dg", 2 -> "mc") - - // add for a diff transaction - MongoStorage.insertVectorStorageEntriesFor("U-A2", changeSetV.toList) - assertEquals( - 4, - MongoStorage.getVectorStorageSizeFor("U-A2")) - - // previous transaction change set should remain same - assertEquals( - 5, - MongoStorage.getVectorStorageSizeFor("U-A1")) - - // test single element entry - MongoStorage.insertVectorStorageEntryFor("U-A1", Map(1->1, 2->4, 3->9)) - assertEquals( - 6, - MongoStorage.getVectorStorageSizeFor("U-A1")) - } - - @Test - def testVectorFetchForKeys = { - - // initially everything 0 - assertEquals( - 0, - MongoStorage.getVectorStorageSizeFor("U-A2")) - - assertEquals( - 0, - MongoStorage.getVectorStorageSizeFor("U-A1")) - - // get some stuff - changeSetV += "debasish" - changeSetV += List(12, 13, 14) - MongoStorage.insertVectorStorageEntriesFor("U-A1", changeSetV.toList) - - assertEquals( - 2, - MongoStorage.getVectorStorageSizeFor("U-A1")) - - assertEquals( - "debasish", - MongoStorage.getVectorStorageEntryFor("U-A1", 0).asInstanceOf[String]) - - assertEquals( - List(12, 13, 14), - MongoStorage.getVectorStorageEntryFor("U-A1", 1).asInstanceOf[List[Int]]) - - changeSetV.clear - changeSetV += Map(1->1, 2->4, 3->9) - changeSetV += BigInt(2310) - changeSetV += List(100, 200, 300) - MongoStorage.insertVectorStorageEntriesFor("U-A1", changeSetV.toList) - - assertEquals( - 5, - MongoStorage.getVectorStorageSizeFor("U-A1")) - - val r = - MongoStorage.getVectorStorageRangeFor("U-A1", Some(1), None, 3) - - assertEquals(3, r.size) - assertEquals(List(12, 13, 14), r(0).asInstanceOf[List[Int]]) - } - - @Test - def testVectorFetchForNonExistentKeys = { - try { - MongoStorage.getVectorStorageEntryFor("U-A1", 1) - fail("should throw an exception") - } catch {case e: Predef.NoSuchElementException => {}} - - try { - MongoStorage.getVectorStorageRangeFor("U-A1", Some(2), None, 12) - fail("should throw an exception") - } catch {case e: Predef.NoSuchElementException => {}} - } - - @Test - def testMapInsertForTransactionId = { - case class Foo(no: Int, name: String) - fillMap - - // add some more to changeSet - changeSetM += "5" -> Foo(12, "dg") - changeSetM += "6" -> java.util.Calendar.getInstance.getTime - - // insert all into Mongo - MongoStorage.insertMapStorageEntriesFor("U-M1", changeSetM.toList) - assertEquals( - 6, - MongoStorage.getMapStorageSizeFor("U-M1")) - - // individual insert api - MongoStorage.insertMapStorageEntryFor("U-M1", "7", "akka") - MongoStorage.insertMapStorageEntryFor("U-M1", "8", List(23, 25)) - assertEquals( - 8, - MongoStorage.getMapStorageSizeFor("U-M1")) - - // add the same changeSet for another transaction - MongoStorage.insertMapStorageEntriesFor("U-M2", changeSetM.toList) - assertEquals( - 6, - MongoStorage.getMapStorageSizeFor("U-M2")) - - // the first transaction should remain the same - assertEquals( - 8, - MongoStorage.getMapStorageSizeFor("U-M1")) - changeSetM.clear - } - - @Test - def testMapContents = { - fillMap - MongoStorage.insertMapStorageEntriesFor("U-M1", changeSetM.toList) - MongoStorage.getMapStorageEntryFor("U-M1", "2") match { - case Some(x) => assertEquals("peter", x.asInstanceOf[String]) - case None => fail("should fetch peter") - } - MongoStorage.getMapStorageEntryFor("U-M1", "4") match { - case Some(x) => assertEquals(3, x.asInstanceOf[List[Int]].size) - case None => fail("should fetch list") - } - MongoStorage.getMapStorageEntryFor("U-M1", "3") match { - case Some(x) => assertEquals(2, x.asInstanceOf[List[Int]].size) - case None => fail("should fetch list") - } - - // get the entire map - val l: List[Tuple2[AnyRef, AnyRef]] = - MongoStorage.getMapStorageFor("U-M1") - - assertEquals(4, l.size) - assertTrue(l.map(_._1).contains("1")) - assertTrue(l.map(_._1).contains("2")) - assertTrue(l.map(_._1).contains("3")) - assertTrue(l.map(_._1).contains("4")) - - assertTrue(l.map(_._2).contains("john")) - - // trying to fetch for a non-existent transaction will throw - try { - MongoStorage.getMapStorageFor("U-M2") - fail("should throw an exception") - } catch {case e: Predef.NoSuchElementException => {}} - - changeSetM.clear - } - - @Test - def testMapContentsByRange = { - fillMap - changeSetM += "5" -> Map(1 -> "dg", 2 -> "mc") - MongoStorage.insertMapStorageEntriesFor("U-M1", changeSetM.toList) - - // specify start and count - val l: List[Tuple2[AnyRef, AnyRef]] = - MongoStorage.getMapStorageRangeFor( - "U-M1", Some(Integer.valueOf(2)), None, 3) - - assertEquals(3, l.size) - assertEquals("3", l(0)._1.asInstanceOf[String]) - assertEquals(List(100, 200), l(0)._2.asInstanceOf[List[Int]]) - assertEquals("4", l(1)._1.asInstanceOf[String]) - assertEquals(List(10, 20, 30), l(1)._2.asInstanceOf[List[Int]]) - - // specify start, finish and count where finish - start == count - assertEquals(3, - MongoStorage.getMapStorageRangeFor( - "U-M1", Some(Integer.valueOf(2)), Some(Integer.valueOf(5)), 3).size) - - // specify start, finish and count where finish - start > count - assertEquals(3, - MongoStorage.getMapStorageRangeFor( - "U-M1", Some(Integer.valueOf(2)), Some(Integer.valueOf(9)), 3).size) - - // do not specify start or finish - assertEquals(3, - MongoStorage.getMapStorageRangeFor( - "U-M1", None, None, 3).size) - - // specify finish and count - assertEquals(3, - MongoStorage.getMapStorageRangeFor( - "U-M1", None, Some(Integer.valueOf(3)), 3).size) - - // specify start, finish and count where finish < start - assertEquals(3, - MongoStorage.getMapStorageRangeFor( - "U-M1", Some(Integer.valueOf(2)), Some(Integer.valueOf(1)), 3).size) - - changeSetM.clear - } - - @Test - def testMapStorageRemove = { - fillMap - changeSetM += "5" -> Map(1 -> "dg", 2 -> "mc") - - MongoStorage.insertMapStorageEntriesFor("U-M1", changeSetM.toList) - assertEquals(5, - MongoStorage.getMapStorageSizeFor("U-M1")) - - // remove key "3" - MongoStorage.removeMapStorageFor("U-M1", "3") - assertEquals(4, - MongoStorage.getMapStorageSizeFor("U-M1")) - - try { - MongoStorage.getMapStorageEntryFor("U-M1", "3") - fail("should throw exception") - } catch { case e => {}} - - // remove the whole stuff - MongoStorage.removeMapStorageFor("U-M1") - - try { - MongoStorage.getMapStorageFor("U-M1") - fail("should throw exception") - } catch { case e: NoSuchElementException => {}} - - changeSetM.clear - } - - private def fillMap = { - changeSetM += "1" -> "john" - changeSetM += "2" -> "peter" - changeSetM += "3" -> List(100, 200) - changeSetM += "4" -> List(10, 20, 30) - changeSetM - } - - @Test - def testRefStorage = { - MongoStorage.getRefStorageFor("U-R1") match { - case None => - case Some(o) => fail("should be None") - } - - val m = Map("1"->1, "2"->4, "3"->9) - MongoStorage.insertRefStorageFor("U-R1", m) - MongoStorage.getRefStorageFor("U-R1") match { - case None => fail("should not be empty") - case Some(r) => { - val a = r.asInstanceOf[Map[String, Int]] - assertEquals(a.size, 3) - assertEquals(a.get("1").get, 1) - assertEquals(a.get("2").get, 4) - assertEquals(a.get("3").get, 9) - } - } - - // insert another one - // the previous one should be replaced - val b = List("100", "jonas") - MongoStorage.insertRefStorageFor("U-R1", b) - MongoStorage.getRefStorageFor("U-R1") match { - case None => fail("should not be empty") - case Some(r) => { - val a = r.asInstanceOf[List[String]] - assertEquals("100", a(0)) - assertEquals("jonas", a(1)) - } - } - } -} +package se.scalablesolutions.akka.kernel.state + +import junit.framework.TestCase + +import org.junit.{Test, Before} +import org.junit.Assert._ +import dispatch.json._ +import dispatch.json.Js._ + +class MongoStorageSpec extends TestCase { + + val changeSetV = new scala.collection.mutable.ArrayBuffer[AnyRef] + val changeSetM = new scala.collection.mutable.HashMap[AnyRef, AnyRef] + + override def setUp = { + MongoStorage.coll.drop + } + + @Test + def testVectorInsertForTransactionId = { + changeSetV += "debasish" // string + changeSetV += List(1, 2, 3) // Scala List + changeSetV += List(100, 200) + MongoStorage.insertVectorStorageEntriesFor("U-A1", changeSetV.toList) + assertEquals( + 3, + MongoStorage.getVectorStorageSizeFor("U-A1")) + changeSetV.clear + + // changeSetV should be reinitialized + changeSetV += List(12, 23, 45) + changeSetV += "maulindu" + MongoStorage.insertVectorStorageEntriesFor("U-A1", changeSetV.toList) + assertEquals( + 5, + MongoStorage.getVectorStorageSizeFor("U-A1")) + + // add more to the same changeSetV + changeSetV += "ramanendu" + changeSetV += Map(1 -> "dg", 2 -> "mc") + + // add for a diff transaction + MongoStorage.insertVectorStorageEntriesFor("U-A2", changeSetV.toList) + assertEquals( + 4, + MongoStorage.getVectorStorageSizeFor("U-A2")) + + // previous transaction change set should remain same + assertEquals( + 5, + MongoStorage.getVectorStorageSizeFor("U-A1")) + + // test single element entry + MongoStorage.insertVectorStorageEntryFor("U-A1", Map(1->1, 2->4, 3->9)) + assertEquals( + 6, + MongoStorage.getVectorStorageSizeFor("U-A1")) + } + + @Test + def testVectorFetchForKeys = { + + // initially everything 0 + assertEquals( + 0, + MongoStorage.getVectorStorageSizeFor("U-A2")) + + assertEquals( + 0, + MongoStorage.getVectorStorageSizeFor("U-A1")) + + // get some stuff + changeSetV += "debasish" + changeSetV += List(BigDecimal(12), BigDecimal(13), BigDecimal(14)) + MongoStorage.insertVectorStorageEntriesFor("U-A1", changeSetV.toList) + + assertEquals( + 2, + MongoStorage.getVectorStorageSizeFor("U-A1")) + + val JsString(str) = MongoStorage.getVectorStorageEntryFor("U-A1", 0).asInstanceOf[JsString] + assertEquals("debasish", str) + + import dispatch.json.Js._ + + val l = MongoStorage.getVectorStorageEntryFor("U-A1", 1).asInstanceOf[JsValue] + val num_list = list ! num + val num_list(l0) = l + assertEquals(List(12, 13, 14), l0) + + changeSetV.clear + changeSetV += Map(1->1, 2->4, 3->9) + changeSetV += BigInt(2310) + changeSetV += List(100, 200, 300) + MongoStorage.insertVectorStorageEntriesFor("U-A1", changeSetV.toList) + + assertEquals( + 5, + MongoStorage.getVectorStorageSizeFor("U-A1")) + + val r = + MongoStorage.getVectorStorageRangeFor("U-A1", Some(1), None, 3) + + assertEquals(3, r.size) + val lr = r(0).asInstanceOf[JsValue] + val num_list(l1) = lr + assertEquals(List(12, 13, 14), l1) + } + + @Test + def testVectorFetchForNonExistentKeys = { + try { + MongoStorage.getVectorStorageEntryFor("U-A1", 1) + fail("should throw an exception") + } catch {case e: Predef.NoSuchElementException => {}} + + try { + MongoStorage.getVectorStorageRangeFor("U-A1", Some(2), None, 12) + fail("should throw an exception") + } catch {case e: Predef.NoSuchElementException => {}} + } + + @Test + def testMapInsertForTransactionId = { + case class Foo(no: Int, name: String) + fillMap + + // add some more to changeSet + changeSetM += "5" -> Foo(12, "dg") + changeSetM += "6" -> java.util.Calendar.getInstance.getTime + + // insert all into Mongo + MongoStorage.insertMapStorageEntriesFor("U-M1", changeSetM.toList) + assertEquals( + 6, + MongoStorage.getMapStorageSizeFor("U-M1")) + + // individual insert api + MongoStorage.insertMapStorageEntryFor("U-M1", "7", "akka") + MongoStorage.insertMapStorageEntryFor("U-M1", "8", List(23, 25)) + assertEquals( + 8, + MongoStorage.getMapStorageSizeFor("U-M1")) + + // add the same changeSet for another transaction + MongoStorage.insertMapStorageEntriesFor("U-M2", changeSetM.toList) + assertEquals( + 6, + MongoStorage.getMapStorageSizeFor("U-M2")) + + // the first transaction should remain the same + assertEquals( + 8, + MongoStorage.getMapStorageSizeFor("U-M1")) + changeSetM.clear + } + + @Test + def testMapContents = { + fillMap + MongoStorage.insertMapStorageEntriesFor("U-M1", changeSetM.toList) + MongoStorage.getMapStorageEntryFor("U-M1", "2") match { + case Some(x) => { + val JsString(str) = x.asInstanceOf[JsValue] + assertEquals("peter", str) + } + case None => fail("should fetch peter") + } + MongoStorage.getMapStorageEntryFor("U-M1", "4") match { + case Some(x) => { + val num_list = list ! num + val num_list(l0) = x.asInstanceOf[JsValue] + assertEquals(3, l0.size) + } + case None => fail("should fetch list") + } + MongoStorage.getMapStorageEntryFor("U-M1", "3") match { + case Some(x) => { + val num_list = list ! num + val num_list(l0) = x.asInstanceOf[JsValue] + assertEquals(2, l0.size) + } + case None => fail("should fetch list") + } + + // get the entire map + val l: List[Tuple2[AnyRef, AnyRef]] = + MongoStorage.getMapStorageFor("U-M1") + + assertEquals(4, l.size) + assertTrue(l.map(_._1).contains("1")) + assertTrue(l.map(_._1).contains("2")) + assertTrue(l.map(_._1).contains("3")) + assertTrue(l.map(_._1).contains("4")) + + val JsString(str) = l.filter(_._1 == "2").first._2 + assertEquals(str, "peter") + + // trying to fetch for a non-existent transaction will throw + try { + MongoStorage.getMapStorageFor("U-M2") + fail("should throw an exception") + } catch {case e: Predef.NoSuchElementException => {}} + + changeSetM.clear + } + + @Test + def testMapContentsByRange = { + fillMap + changeSetM += "5" -> Map(1 -> "dg", 2 -> "mc") + MongoStorage.insertMapStorageEntriesFor("U-M1", changeSetM.toList) + + // specify start and count + val l: List[Tuple2[AnyRef, AnyRef]] = + MongoStorage.getMapStorageRangeFor( + "U-M1", Some(Integer.valueOf(2)), None, 3) + + assertEquals(3, l.size) + assertEquals("3", l(0)._1.asInstanceOf[String]) + val lst = l(0)._2.asInstanceOf[JsValue] + val num_list = list ! num + val num_list(l0) = lst + assertEquals(List(100, 200), l0) + assertEquals("4", l(1)._1.asInstanceOf[String]) + val ls = l(1)._2.asInstanceOf[JsValue] + val num_list(l1) = ls + assertEquals(List(10, 20, 30), l1) + + // specify start, finish and count where finish - start == count + assertEquals(3, + MongoStorage.getMapStorageRangeFor( + "U-M1", Some(Integer.valueOf(2)), Some(Integer.valueOf(5)), 3).size) + + // specify start, finish and count where finish - start > count + assertEquals(3, + MongoStorage.getMapStorageRangeFor( + "U-M1", Some(Integer.valueOf(2)), Some(Integer.valueOf(9)), 3).size) + + // do not specify start or finish + assertEquals(3, + MongoStorage.getMapStorageRangeFor( + "U-M1", None, None, 3).size) + + // specify finish and count + assertEquals(3, + MongoStorage.getMapStorageRangeFor( + "U-M1", None, Some(Integer.valueOf(3)), 3).size) + + // specify start, finish and count where finish < start + assertEquals(3, + MongoStorage.getMapStorageRangeFor( + "U-M1", Some(Integer.valueOf(2)), Some(Integer.valueOf(1)), 3).size) + + changeSetM.clear + } + + @Test + def testMapStorageRemove = { + fillMap + changeSetM += "5" -> Map(1 -> "dg", 2 -> "mc") + + MongoStorage.insertMapStorageEntriesFor("U-M1", changeSetM.toList) + assertEquals(5, + MongoStorage.getMapStorageSizeFor("U-M1")) + + // remove key "3" + MongoStorage.removeMapStorageFor("U-M1", "3") + assertEquals(4, + MongoStorage.getMapStorageSizeFor("U-M1")) + + try { + MongoStorage.getMapStorageEntryFor("U-M1", "3") + fail("should throw exception") + } catch { case e => {}} + + // remove the whole stuff + MongoStorage.removeMapStorageFor("U-M1") + + try { + MongoStorage.getMapStorageFor("U-M1") + fail("should throw exception") + } catch { case e: NoSuchElementException => {}} + + changeSetM.clear + } + + private def fillMap = { + changeSetM += "1" -> "john" + changeSetM += "2" -> "peter" + changeSetM += "3" -> List(100, 200) + changeSetM += "4" -> List(10, 20, 30) + changeSetM + } + + @Test + def testRefStorage = { + MongoStorage.getRefStorageFor("U-R1") match { + case None => + case Some(o) => fail("should be None") + } + + val m = Map("1"->1, "2"->4, "3"->9) + MongoStorage.insertRefStorageFor("U-R1", m) + MongoStorage.getRefStorageFor("U-R1") match { + case None => fail("should not be empty") + case Some(r) => { + val a = r.asInstanceOf[JsValue] + val m1 = Symbol("1") ? num + val m2 = Symbol("2") ? num + val m3 = Symbol("3") ? num + + val m1(n1) = a + val m2(n2) = a + val m3(n3) = a + + assertEquals(n1, 1) + assertEquals(n2, 4) + assertEquals(n3, 9) + } + } + + // insert another one + // the previous one should be replaced + val b = List("100", "jonas") + MongoStorage.insertRefStorageFor("U-R1", b) + MongoStorage.getRefStorageFor("U-R1") match { + case None => fail("should not be empty") + case Some(r) => { + val a = r.asInstanceOf[JsValue] + val str_lst = list ! str + val str_lst(l) = a + assertEquals(b, l) + } + } + } +}