PageRenderTime 28ms CodeModel.GetById 14ms app.highlight 12ms RepoModel.GetById 0ms app.codeStats 0ms

/src/test/scala/couch/db/ViewServerWithObjectsSpec.scala

http://scouchdb.googlecode.com/
Scala | 271 lines | 208 code | 52 blank | 11 comment | 0 complexity | 0e5f691fbb814f23f4add93ad4ff99bf MD5 | raw file
  1package couch.db
  2
  3import org.scalatest.Spec
  4import org.scalatest.BeforeAndAfter
  5import org.scalatest.FeatureSuite
  6import org.scalatest.matchers.ShouldMatchers
  7
  8import couch.json._
  9
 10class ViewServerWithObjectsSpec extends Spec with ShouldMatchers with BeforeAndAfter {
 11  
 12  val couch = Couch("127.0.0.1")
 13  val carDb = Db("car_inventory_db")
 14  
 15  override def beforeAll {
 16    try {
 17      couch(carDb.delete)
 18    }
 19    catch {
 20      case _ =>
 21    }
 22    couch(carDb.create)
 23    println(couch(carDb as_str))
 24//    assert(status == 201)
 25    println("** created database")
 26  }
 27  
 28  override def afterAll {
 29    couch(carDb.delete)
 30//    assert(status == 200)
 31    println("** destroyed database")
 32  }
 33  
 34  describe("create records") {
 35    it("should create new records") {
 36      def newCar(carId : String) = Doc(carDb, carId)
 37
 38      // add
 39      couch(newCar("honda_civic_new_red") add CarSaleItem("Honda", "Civic", 16000, "New", "Red"))
 40      couch(newCar("tesla_roadster_new_orange") add CarSaleItem("Tesla", "Roadster", 90000, "New", "Orange"))
 41      couch(newCar("bmw_mini_used_redwhiteblue") add CarSaleItem("BMW", "Mini", 12500, "Used", "Red/White/Blue"))
 42      couch(newCar("ford_mustang_used_silver") add CarSaleItem("Ford", "Mustang", 14500, "Used", "Silver"))
 43      couch(newCar("geo_metro_used_red") add CarSaleItem("Geo", "Metro", 7500, "Used", "Red"))
 44    }
 45  }
 46  
 47  describe("Create, query, view : only maps") {
 48    it("should identify red cars") {
 49       
 50      // query by id to get back the object
 51      // returns a tuple3 of (id, rev, object)
 52      val (id, rev, item) = couch(carDb by_id("bmw_mini_used_redwhiteblue", classOf[CarSaleItem]))
 53      
 54      id should equal("bmw_mini_used_redwhiteblue")
 55      item.make should equal("BMW")
 56      item.model should equal("Mini")
 57
 58      // map function
 59      val redCarsPrice =
 60        """(doc: dispatch.json.JsValue) => {
 61          val (id, rev, car) = couch.json.JsBean.toBean(doc, classOf[couch.db.CarSaleItem]);
 62          if (car.color.contains("Red")) List(List(car.make, car.price)) else Nil
 63        }"""
 64
 65      // map function
 66      val redCars =
 67        """(doc: dispatch.json.JsValue) => {
 68          val (id, rev, car) = couch.json.JsBean.toBean(doc, classOf[couch.db.CarSaleItem]);
 69          if (car.color.contains("Red")) List(List(car.make, car)) else Nil
 70        }"""
 71
 72      val redCarsView = new View(redCars, null)
 73      val redCarsPriceView = new View(redCarsPrice, null)
 74
 75      val cv = DesignDocument("car_views", null, Map[String, View]())
 76      cv.language = "scala"
 77
 78      val rcv = DesignDocument(cv._id, null, Map("red_cars" -> redCarsView, "red_cars_price" -> redCarsPriceView))
 79      rcv.language = "scala"
 80      couch(Doc(carDb, rcv._id) add rcv)
 81
 82      val ls1 = couch(carDb view(
 83        Views builder("car_views/red_cars") build))
 84      println(ls1)
 85      ls1.size should equal(3)
 86                            
 87      val ls2 = couch(carDb view(
 88        Views builder("car_views/red_cars_price") build))
 89      println(ls2)
 90      ls2.size should equal(3)
 91    }
 92  }
 93  
 94  describe("View results fetched as JSON and converted to objects after return") {
 95    it ("should create 3 objects from 3 items in map return") {
 96      val ls1 = couch(carDb view(
 97        Views builder("car_views/red_cars") build))
 98      println(ls1)
 99      ls1.size should equal(3)
100      
101      import dispatch.json.Js._;
102      val objs =
103        ls1.map { car =>
104          val x = Symbol("value") ? obj
105          val x(x_) = car
106          JsBean.toBean(x_, classOf[CarSaleItem])._3
107        }
108      objs.size should equal(3)
109      objs.map(_.make).sort((e1, e2) => (e1 compareTo e2) < 0) should equal(List("BMW", "Geo", "Honda"))
110    }
111  }
112  
113  describe("Returning objects directly from view results (map only)") {
114    it ("should create 3 car objects from 3 items in map return") {
115      val ls1 = couch(carDb view(
116        Views builder("car_views/red_cars") build, classOf[CarSaleItem]))
117      println(ls1)
118      ls1.size should equal(3)
119      ls1.map(_.make).sort((e1, e2) => (e1 compareTo e2) < 0) should equal(List("BMW", "Geo", "Honda"))
120    }
121    it ("should create 3 number objects from 3 items in map return") {
122      val ls1 = couch(carDb view(
123        Views builder("car_views/red_cars_price") build, classOf[BigDecimal]))
124      println(ls1)
125      ls1.size should equal(3)
126      ls1.sort((e1, e2) => (e1 compareTo e2) < 0) should equal(List(7500, 12500, 16000))
127    }
128  }
129  
130  describe("Create, query, view : map and reduce") {
131    it("should identify red cars") {
132       
133      // map function
134      val redCarsPrice =
135        """(doc: dispatch.json.JsValue) => {
136          val (id, rev, car) = couch.json.JsBean.toBean(doc, classOf[couch.db.CarSaleItem]);
137          if (car.color.contains("Red")) List(List(car.make, car.price)) else Nil
138        }"""
139
140      val redfn1 = """(key: List[(String, String)], values: List[dispatch.json.JsNumber], rereduce: Boolean) => {
141          values.foldLeft(BigDecimal(0.00))((s, f) => s + (f match { case dispatch.json.JsNumber(n) => n }))
142        }"""
143      
144      val redCarsPriceView = new View(redCarsPrice, redfn1)
145
146      val cv = DesignDocument("red_car_views", null, Map[String, View]())
147      cv.language = "scala"
148
149      val rcv = DesignDocument(cv._id, null, Map("red_cars_price" -> redCarsPriceView))
150      rcv.language = "scala"
151      couch(Doc(carDb, rcv._id) add rcv)
152
153      val ls2 = couch(carDb view(
154        Views builder("red_car_views/red_cars_price") build))
155      println(ls2)
156       ls2.size should equal(1)
157    }
158  }
159  
160  describe("Create, query, view : map and reduce objects created after returning JSON from view") {
161    it("should identify red cars and find sum of price") {
162       
163      // map function
164      val mapForRedCars =
165        """(doc: dispatch.json.JsValue) => {
166          val (id, rev, car) = couch.json.JsBean.toBean(doc, classOf[couch.db.CarSaleItem]);
167          if (car.color.contains("Red")) List(List(car.make, car)) else Nil
168        }"""
169
170      val reduceToPriceSum = """(key: List[(String, String)], values: List[dispatch.json.JsObject], rereduce: Boolean) => {
171          val objs = values.map(couch.json.JsBean.toBean(_, classOf[couch.db.CarSaleItem])._3).map(_.price)
172          objs.foldLeft(BigDecimal(0.00))(_+_)
173        }"""
174      
175      val redCarsPriceView = new View(mapForRedCars, reduceToPriceSum)
176
177      val cv = DesignDocument("sum_car_views", null, Map[String, View]())
178      cv.language = "scala"
179
180      val rcv = DesignDocument(cv._id, null, Map("red_cars_sum_price" -> redCarsPriceView))
181      rcv.language = "scala"
182      couch(Doc(carDb, rcv._id) add rcv)
183
184      val ls1 = couch(carDb view(
185        Views builder("sum_car_views/red_cars_sum_price") build))
186      println(ls1)
187      ls1.size should equal(1)
188      
189      import dispatch.json.Js._
190      import dispatch.json._
191      val objs =
192        ls1.map { mp =>
193          val x = Symbol("value") ? num
194          val x(x_) = mp
195          x_
196        }
197      objs.size should equal(1)
198      objs.head should equal(36000)
199    }
200    it("should identify red cars and find max price") {
201       
202      // map function to spit out red cars
203      val mapForRedCars =
204        """(doc: dispatch.json.JsValue) => {
205          val (id, rev, car) = couch.json.JsBean.toBean(doc, classOf[couch.db.CarSaleItem]);
206          if (car.color.contains("Red")) List(List(car.make, car)) else Nil
207        }"""
208
209      // reduce function to get max price
210      val reduceToMaxPrice = """(key: List[(String, String)], values: List[dispatch.json.JsObject], rereduce: Boolean) => {
211          values.map(couch.json.JsBean.toBean(_, classOf[couch.db.CarSaleItem])._3).map(_.price).sort((e1,e2) => (e1 > e2)).head
212        }"""
213      
214      val redCarsPriceView = new View(mapForRedCars, reduceToMaxPrice)
215
216      val cv = DesignDocument("max_car_views", null, Map[String, View]())
217      cv.language = "scala"
218
219      val rcv = DesignDocument(cv._id, null, Map("red_cars_max_price" -> redCarsPriceView))
220      rcv.language = "scala"
221      couch(Doc(carDb, rcv._id) add rcv)
222
223      val ls1 = couch(carDb view(
224        Views builder("max_car_views/red_cars_max_price") build))
225      println(ls1)
226      ls1.size should equal(1)
227      
228      import dispatch.json.Js._
229      import dispatch.json._
230      val objs =
231        ls1.map { mp =>
232          val x = Symbol("value") ? num
233          val x(x_) = mp
234          x_
235        }
236      objs.size should equal(1)
237      objs.head should equal(16000)
238    }
239  }
240  
241  describe("Returning objects directly from view results in reduce") {
242    it ("should create 1 number objects from reduce") {
243      val ls1 = couch(carDb view(
244        Views builder("max_car_views/red_cars_max_price") build, classOf[BigDecimal]))
245      println(ls1)
246      ls1.size should equal(1)
247      ls1(0) should equal(16000)
248    }
249  }
250}
251
252import scala.reflect._
253
254@BeanInfo
255case class CarSaleItem(make : String, model : String, price : BigDecimal, condition : String, color : String) {
256
257    def this(make : String, model : String, price : Int, condition : String, color : String) =
258        this(make, model, BigDecimal.int2bigDecimal(price), condition, color)
259
260    private [db] def this() = this(null, null, 0, null, null)
261
262    override def toString = "A " + condition + " " + color + " " + make + " " + model + " for $" + price
263}
264
265@BeanInfo
266case class ItemPrice(store: String, item: String, price: Number) {
267
268    private [db] def this() = this(null, null, null)
269
270    override def toString = "shop = " + store + " for item " + item + " @ " + price
271}