PageRenderTime 39ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/casbah-core/src/test/scala/LazyDecodingSpec.scala

http://github.com/mongodb/casbah
Scala | 190 lines | 138 code | 21 blank | 31 comment | 3 complexity | 6015e6d99dbcb109c07a725820c18726 MD5 | raw file
Possible License(s): Apache-2.0
  1. /**
  2. * Copyright (c) 2010 10gen, Inc. <http://10gen.com>
  3. * Copyright (c) 2009, 2010 Novus Partners, Inc. <http://novus.com>
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. * For questions and comments about this product, please see the project page at:
  18. *
  19. * http://github.com/mongodb/casbah
  20. *
  21. */
  22. package com.mongodb.casbah.test
  23. import com.mongodb.casbah.commons.test.CasbahMutableSpecification
  24. import com.mongodb.casbah._
  25. import com.mongodb.casbah.util.bson.decoding.OptimizedLazyDBObject
  26. import java.util.{UUID , Date}
  27. import org.bson.types.{MinKey, MaxKey, BSONTimestamp, Binary}
  28. import java.util.regex.Pattern
  29. class LazyDecodingSpec extends CasbahMutableSpecification {
  30. implicit val mongoInt = MongoConnection()("casbahIntegration")
  31. implicit val mongoTest = MongoConnection()("casbahTest_Lazy")
  32. val x = 10
  33. "Lazy Collections" should {
  34. "Be fetchable, and return LazyCursors and LazyDBObjects" in {
  35. val coll = mongoInt.lazyCollection("books")
  36. coll must haveClass[LazyMongoCollection]
  37. coll.find() must haveClass[LazyMongoCursor]
  38. coll.find().next() must haveClass[OptimizedLazyDBObject]
  39. }
  40. "Perform better, overall, than Standard DBObjects in %d iterations".format(x) in {
  41. def fetchBook(obj: DBObject) ={
  42. val start = System.nanoTime()
  43. val id = obj.getAs[ObjectId]("_id")
  44. val isbn = obj.getAs[String]("isbn")
  45. val author = obj.getAs[String]("author")
  46. val discountPrice = obj.expand[Double]("price.discount")
  47. val msrpPrice = obj.expand[Double]("price.msrp")
  48. val publicationYear = obj.getAs[Int]("publicationYear")
  49. val tags = obj.getAs[Seq[String]]("tags")
  50. val title = obj.getAs[String]("title")
  51. ( System.nanoTime() - start ).toDouble / 1000000000
  52. }
  53. val stdColl = mongoInt("books")
  54. val lazyColl = mongoInt.lazyCollection("books")
  55. val stdCount = stdColl.count
  56. val lazyCount = lazyColl.count
  57. stdCount must beGreaterThan(0L)
  58. lazyCount must beGreaterThan(0L)
  59. stdCount must_== ( lazyCount )
  60. def runSum(c: MongoCollection) =
  61. c.find().map(doc => fetchBook(doc)).sum
  62. var stdTotal = 0.0
  63. for ( i <- 0 until x )
  64. stdTotal += runSum(stdColl)
  65. var lazyTotal = 0.0
  66. for ( i <- 0 until x )
  67. lazyTotal += runSum(lazyColl)
  68. val stdTime = ( stdTotal / stdCount ) / x
  69. val lazyTime = ( lazyTotal / lazyCount ) / x
  70. System.err.println("[Total: %12.6f seconds] Average Seconds Per Doc STD: %2.6f".format(stdTotal , stdTime))
  71. System.err.println("[Total: %12.6f seconds] Average Seconds Per Doc Lazy: %2.6f".format(lazyTotal , lazyTime))
  72. lazyTotal must beGreaterThan(0.0)
  73. stdTotal must beGreaterThan(0.0)
  74. //lazyTotal must beLessThan(stdTotal)
  75. //lazyTime must beLessThan(stdTime)
  76. }
  77. "Properly decode and read all supported/expected datatypes" in {
  78. val oid = new ObjectId
  79. val testOid = new ObjectId
  80. val testRefOid = mongoInt("books").findOne().get.getAs[ObjectId]("_id")
  81. val testDoc = MongoDBObject("abc" -> "12345")
  82. val testArr = Array[String]("foo" , "bar" , "baz" , "x" , "y" , "z")
  83. val testList = MongoDBList("foo" , "bar" , "baz" , "x" , "y" , "z")
  84. val testTsp = new BSONTimestamp
  85. val testDate = new Date
  86. val testBin = new Binary(Array[Byte]('x' , 'y' , 'z' , 5 , 4 , 3 , 2 , 1))
  87. val testUUID = UUID.randomUUID
  88. val testRE = "^test.*regex.*xyz$".r
  89. val inDoc = MongoDBObject("_id" -> oid ,
  90. "null" -> null ,
  91. "max" -> new MaxKey ,
  92. "min" -> new MinKey ,
  93. "booleanTrue" -> true ,
  94. "booleanFalse" -> false ,
  95. "int1" -> 1 ,
  96. "int1500" -> 1500 ,
  97. "int3753" -> 3753 ,
  98. "tsp" -> testTsp ,
  99. "date" -> testDate ,
  100. "long5" -> 5L ,
  101. "long3254525" -> 3254525L ,
  102. "float324_582" -> 324.582F ,
  103. "double245_6289" -> 245.6289 ,
  104. "oid" -> testOid ,
  105. /*
  106. // Symbol Wonky in java driver
  107. "symbol" -> new Symbol("foobar"),
  108. // code wonky in java driver
  109. "code" -> new Code("var x = 12345;"),
  110. // Code w/ scope wonky in java driver
  111. "code_scoped" -> new CodeWScope("return x * 500;", testDoc),
  112. */
  113. "str" -> "foobarbaz" ,
  114. "ref" -> new DBRef(mongoInt.underlying, "books" , testRefOid) ,
  115. "object" -> testDoc ,
  116. "array" -> testArr ,
  117. "list" -> testList , // same as array technically
  118. "binary" -> testBin ,
  119. "uuid" -> testUUID ,
  120. "regex" -> testRE
  121. )
  122. def readDoc(coll: MongoCollection) = {
  123. coll.drop()
  124. coll += inDoc
  125. coll.findOne(MongoDBObject("_id" -> oid)) match {
  126. case None =>
  127. throw new IllegalArgumentException("No matching object in database.")
  128. case Some(doc: DBObject) =>
  129. doc must haveEntry("_id" -> oid )
  130. doc.get("null") must beNull
  131. doc.getAs[MaxKey]("max") must beSome[MaxKey] // todo - Proper scala side matchers on MinKey/MaxKey
  132. doc.getAs[MinKey]("min") must beSome[MinKey]
  133. doc must haveEntry("booleanTrue" -> true )
  134. doc must haveEntry("booleanFalse" -> false )
  135. doc must haveEntry("int1" -> 1 )
  136. doc must haveEntry("int1500" -> 1500 )
  137. doc must haveEntry("int3753" -> 3753 )
  138. doc must haveEntry("tsp" -> testTsp )
  139. doc must haveEntry("date" -> testDate )
  140. doc must haveEntry("long5" -> 5L )
  141. doc must haveEntry("long3254525" -> 3254525L )
  142. doc must haveEntry("float324_582" -> 324.5820007324219 ) // how mongo actually ends up storing the previous float
  143. doc must haveEntry("double245_6289" -> 245.6289 )
  144. doc must haveEntry("oid" -> testOid )
  145. doc must haveEntry("str" -> "foobarbaz" )
  146. doc must haveEntry("uuid" -> testUUID)
  147. doc must haveEntry("object.abc" -> testDoc.get("abc") )
  148. doc.getAs[Pattern]("regex").get.pattern() must_==( testRE.pattern.pattern() )
  149. }
  150. }
  151. "Normal DBObjects decode properly" in {
  152. readDoc(mongoTest("readNormal"))
  153. }
  154. "Lazy DBObjects decode properly" in {
  155. readDoc(mongoTest("readLazy"))
  156. }
  157. }
  158. "Iterate their keysets correctly" in {
  159. import scalaj.collection.Imports._
  160. val coll = mongoInt.lazyCollection("books")
  161. for (doc <- coll; k <- doc.keySet) {
  162. k must not beNull
  163. val v = doc.get(k)
  164. v must not beNull
  165. }
  166. coll.size must beGreaterThan(0)
  167. }
  168. }
  169. }