You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@s2graph.apache.org by da...@apache.org on 2016/01/13 10:07:35 UTC

[2/7] incubator-s2graph git commit: [S2GRAPH-7] Abstract common codes for rest project into s2core

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/s2rest_play/conf/logger.xml
----------------------------------------------------------------------
diff --git a/s2rest_play/conf/logger.xml b/s2rest_play/conf/logger.xml
new file mode 100644
index 0000000..2d767c2
--- /dev/null
+++ b/s2rest_play/conf/logger.xml
@@ -0,0 +1,83 @@
+<configuration>
+
+    <conversionRule conversionWord="coloredLevel" converterClass="play.api.Logger$ColoredLevel"/>
+
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>logs/application.log</file>
+
+        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+            <fileNamePattern>logs/application.%i.log</fileNamePattern>
+            <minIndex>1</minIndex>
+            <maxIndex>9</maxIndex>
+        </rollingPolicy>
+
+        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+            <maxFileSize>500MB</maxFileSize>
+        </triggeringPolicy>
+        <encoder>
+            <pattern>%date [%level] [%logger] [%thread] - %message %xException%n</pattern>
+        </encoder>
+    </appender>
+
+
+    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>logs/error.log</file>
+        <append>true</append>
+        <encoder>
+            <pattern>%date [%level] [%logger] [%thread] - %message %xException%n</pattern>
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>logs/error.log.%d.%i</fileNamePattern>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>500MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <maxHistory>3</maxHistory>
+        </rollingPolicy>
+    </appender>
+
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%coloredLevel %logger{15} - %message%n%xException%n</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="ACTOR" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>logs/actor.log</file>
+        <append>true</append>
+        <encoder>
+            <pattern>%date [%level] [%logger] [%thread] - %message %xException%n</pattern>
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>logs/actor.log.%d.%i</fileNamePattern>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>200MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <maxHistory>7</maxHistory>
+        </rollingPolicy>
+    </appender>
+
+    <logger name="play" level="INFO">
+        <appender-ref ref="STDOUT"/>
+        <appender-ref ref="FILE"/>
+    </logger>
+
+    <logger name="application" level="INFO">
+        <appender-ref ref="STDOUT"/>
+        <appender-ref ref="FILE"/>
+    </logger>
+
+    <logger name="error" level="INFO">
+        <appender-ref ref="STDOUT"/>
+        <appender-ref ref="ERROR"/>
+    </logger>
+
+    <logger name="actor" level="INFO">
+        <appender-ref ref="ACTOR"/>
+    </logger>
+
+    <logger name="akka" level="INFO">
+        <appender-ref ref="STDOUT"/>
+        <appender-ref ref="FILE"/>
+    </logger>
+
+</configuration>

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/s2rest_play/conf/reference.conf
----------------------------------------------------------------------
diff --git a/s2rest_play/conf/reference.conf b/s2rest_play/conf/reference.conf
new file mode 100644
index 0000000..a992e5d
--- /dev/null
+++ b/s2rest_play/conf/reference.conf
@@ -0,0 +1,131 @@
+# This is the main configuration file for the application.
+# ~~~~~
+
+# Secret key
+# ~~~~~
+# The secret key is used to secure cryptographics functions.
+#
+# This must be changed for production, but we recommend not changing it in this file.
+#
+# See http://www.playframework.com/documentation/latest/ApplicationSecret for more details.
+application.secret="/`==g^yr2DNnZGK_L^rguLZeR`60uLOVgY@OhyTv:maatl:Tl>9or/d1xME3b/Pi"
+
+# The application languages
+# ~~~~~
+application.langs="en"
+
+# Global object class
+# ~~~~~
+# Define the Global object class for this application.
+# Default to Global in the root package.
+# application.global=Global
+
+# Router
+# ~~~~~
+# Define the Router object to use for this application.
+# This router will be looked up first when the application is starting up,
+# so make sure this is the entry point.
+# Furthermore, it's assumed your route file is named properly.
+# So for an application router like `my.application.Router`,
+# you may need to define a router file `conf/my.application.routes`.
+# Default to Routes in the root package (and conf/routes)
+# application.router=my.application.Routes
+
+# Database configuration
+# ~~~~~
+# You can declare as many datasources as you want.
+# By convention, the default datasource is named `default`
+#
+# db.default.driver=org.h2.Driver
+# db.default.url="jdbc:h2:mem:play"
+# db.default.user=sa
+# db.default.password=""
+
+# Evolutions
+# ~~~~~
+# You can disable evolutions if needed
+# evolutionplugin=disabled
+
+# Logger
+# ~~~~~
+# You can also configure logback (http://logback.qos.ch/),
+# by providing an application-logger.xml file in the conf directory.
+
+# Root logger:
+logger.root=ERROR
+
+# Logger used by the framework:
+logger.play=INFO
+
+# Logger provided to your application:
+logger.application=DEBUG
+
+# APP PHASE
+phase=dev
+host=localhost
+
+# DB
+s2graph.models.table.name="models-dev"
+hbase.zookeeper.quorum=${host}
+db.default.url="jdbc:mysql://"${host}":3306/graph_dev"
+# Query server
+is.query.server=true
+is.write.server=true
+query.hard.limit=100000
+
+# Local Cache
+cache.ttl.seconds=60
+cache.max.size=100000
+
+# HBASE
+#hbase.client.operation.timeout=1000
+#async.hbase.client.flush.interval=100
+hbase.table.compression.algorithm="gz"
+
+# Asynchbase
+hbase.client.retries.number=100
+hbase.rpcs.buffered_flush_interval=100
+hbase.rpc.timeout=0
+#hbase.nsre.high_watermark=1000000
+#hbase.timer.tick=5
+#hbase.timer.ticks_per_wheel=5
+
+# Kafka
+kafka.metadata.broker.list=${host}
+kafka.producer.pool.size=0
+
+# HTTP
+parsers.text.maxLength=512K
+parsers.json.maxLength=512K
+trustxforwarded=false
+
+# Local Queue Actor
+local.queue.actor.max.queue.size=100000
+local.queue.actor.rate.limit=1000000
+
+# local retry number
+max.retry.number=100
+max.back.off=50
+delete.all.fetch.size=10000
+hbase.fail.prob=-1.0
+
+# max allowd edges for deleteAll is multiply of above two configuration.
+
+# set global obejct package, TODO: remove global
+application.global=com.kakao.s2graph.rest.Global
+
+akka {
+  loggers = ["akka.event.slf4j.Slf4jLogger"]
+  loglevel = "DEBUG"
+}
+
+
+# Future cache.
+future.cache.max.size=100000
+future.cache.expire.after.write=10000
+future.cache.expire.after.access=5000
+
+
+# Counter
+redis.instances = [${host}]
+

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/s2rest_play/conf/routes
----------------------------------------------------------------------
diff --git a/s2rest_play/conf/routes b/s2rest_play/conf/routes
new file mode 100644
index 0000000..df4a1ee
--- /dev/null
+++ b/s2rest_play/conf/routes
@@ -0,0 +1,124 @@
+# Routes
+# This file defines all application routes (Higher priority routes first)
+# ~~~~
+
+
+# publish
+#POST   /publish/:topic                                                        controllers.PublishController.publish(topic)
+POST        /publish/:topic                                               controllers.PublishController.mutateBulk(topic)
+POST        /publishOnly/:topic                                           controllers.PublishController.publishOnly(topic)
+
+#### Health Check
+#GET    /health_check.html                                                     controllers.Assets.at(path="/public", file="health_check.html")
+GET         /health_check.html                                            controllers.ApplicationController.healthCheck()
+PUT         /health_check/:isHealthy                                      controllers.ApplicationController.updateHealthCheck(isHealthy: Boolean)
+
+## Edge
+POST        /graphs/edges/insert                                          controllers.EdgeController.inserts()
+POST        /graphs/edges/insertWithWait                                  controllers.EdgeController.insertsWithWait()
+POST        /graphs/edges/insertBulk                                      controllers.EdgeController.insertsBulk()
+POST        /graphs/edges/delete                                          controllers.EdgeController.deletes()
+POST        /graphs/edges/deleteWithWait                                  controllers.EdgeController.deletesWithWait()
+POST        /graphs/edges/deleteAll                                       controllers.EdgeController.deleteAll()
+POST        /graphs/edges/update                                          controllers.EdgeController.updates()
+POST        /graphs/edges/updateWithWait                                  controllers.EdgeController.updatesWithWait()
+POST        /graphs/edges/increment                                       controllers.EdgeController.increments()
+POST        /graphs/edges/incrementCount                                  controllers.EdgeController.incrementCounts()
+POST        /graphs/edges/bulk                                            controllers.EdgeController.mutateBulk()
+
+## Vertex
+POST        /graphs/vertices/insert                                       controllers.VertexController.inserts()
+POST        /graphs/vertices/insertWithWait                               controllers.VertexController.insertsWithWait()
+POST        /graphs/vertices/insert/:serviceName/:columnName              controllers.VertexController.insertsSimple(serviceName, columnName)
+POST        /graphs/vertices/delete                                       controllers.VertexController.deletes()
+POST        /graphs/vertices/deleteWithWait                               controllers.VertexController.deletesWithWait()
+POST        /graphs/vertices/delete/:serviceName/:columnName              controllers.VertexController.deletesSimple(serviceName, columnName)
+POST        /graphs/vertices/deleteAll                                    controllers.VertexController.deletesAll()
+POST        /graphs/vertices/deleteAll/:serviceName/:columnName           controllers.VertexController.deletesAllSimple(serviceName, columnName)
+
+
+### SELECT Edges
+POST        /graphs/getEdges                                              controllers.QueryController.getEdges()
+POST        /graphs/getEdges/grouped                                      controllers.QueryController.getEdgesWithGrouping()
+POST        /graphs/getEdgesExcluded                                      controllers.QueryController.getEdgesExcluded()
+POST        /graphs/getEdgesExcluded/grouped                              controllers.QueryController.getEdgesExcludedWithGrouping()
+POST        /graphs/checkEdges                                            controllers.QueryController.checkEdges()
+
+### this will be deprecated
+POST        /graphs/getEdgesGrouped                                       controllers.QueryController.getEdgesGrouped()
+POST        /graphs/getEdgesGroupedExcluded                               controllers.QueryController.getEdgesGroupedExcluded()
+POST        /graphs/getEdgesGroupedExcludedFormatted                      controllers.QueryController.getEdgesGroupedExcludedFormatted()
+GET         /graphs/getEdge/:srcId/:tgtId/:labelName/:direction           controllers.QueryController.getEdge(srcId, tgtId, labelName, direction)
+
+
+### SELECT Vertices
+#POST   /graphs/getVertex                                                      controllers.QueryController.getVertex()
+POST        /graphs/getVertices                                           controllers.QueryController.getVertices()
+
+
+#### ADMIN
+POST        /graphs/createService                                         controllers.AdminController.createService()
+GET         /graphs/getService/:serviceName                               controllers.AdminController.getService(serviceName)
+GET         /graphs/getLabels/:serviceName                                controllers.AdminController.getLabels(serviceName)
+POST        /graphs/createLabel                                           controllers.AdminController.createLabel()
+POST        /graphs/addIndex                                              controllers.AdminController.addIndex()
+GET         /graphs/getLabel/:labelName                                   controllers.AdminController.getLabel(labelName)
+PUT         /graphs/deleteLabel/:labelName                                controllers.AdminController.deleteLabel(labelName)
+
+POST        /graphs/addProp/:labelName                                    controllers.AdminController.addProp(labelName)
+POST        /graphs/createServiceColumn                                   controllers.AdminController.createServiceColumn()
+PUT         /graphs/deleteServiceColumn/:serviceName/:columnName          controllers.AdminController.deleteServiceColumn(serviceName, columnName)
+POST        /graphs/addServiceColumnProp/:serviceName/:columnName         controllers.AdminController.addServiceColumnProp(serviceName, columnName)
+POST        /graphs/addServiceColumnProps/:serviceName/:columnName        controllers.AdminController.addServiceColumnProps(serviceName, columnName)
+GET         /graphs/getServiceColumn/:serviceName/:columnName             controllers.AdminController.getServiceColumn(serviceName, columnName)
+POST        /graphs/createHTable                                          controllers.AdminController.createHTable()
+
+
+
+
+#### TEST
+#GET    /graphs/testGetEdges/:label/:limit/:friendCntStep                       controllers.QueryController.testGetEdges(label, limit: Int, friendCntStep: Int)
+#GET    /graphs/testGetEdges2/:label1/:limit1/:label2/:limit2                   controllers.QueryController.testGetEdges2(label1, limit1: Int, label2, limit2: Int)
+#GET    /graphs/testGetEdges3/:label1/:limit1/:label2/:limit2/:label3/:limit3   controllers.QueryController.testGetEdges3(label1, limit1: Int, label2, limit2: Int, label3, limit3: Int)
+POST        /ping                                                         controllers.TestController.ping()
+POST        /pingAsync                                                    controllers.TestController.pingAsync()
+GET         /graphs/testId                                                controllers.TestController.getRandomId()
+
+# Map static resources from the /public folder to the /assets URL path
+GET         /images/*file                                                 controllers.Assets.at(path="/public/images", file)
+GET         /javascripts/*file                                            controllers.Assets.at(path="/public/javascripts", file)
+GET         /stylesheets/*file                                            controllers.Assets.at(path="/public/stylesheets", file)
+GET         /font-awesome-4.1.0/*file                                     controllers.Assets.at(path="/public/font-awesome-4.1.0", file)
+GET         /swagger/*file                                                controllers.Assets.at(path="/public/swagger-ui", file)
+
+
+# AdminController API
+#GET    /admin/services                                                         controllers.AdminController.allServices
+GET         /admin/labels/:serviceName                                    controllers.AdminController.getLabels(serviceName)
+#POST   /admin/labels/delete/:zkAddr/:tableName/:labelIds/:minTs/:maxTs         controllers.AdminController.deleteEdges(zkAddr, tableName, labelIds, minTs: Long, maxTs: Long)
+#POST   /admin/labels/deleteAll/:zkAddr/:tableName/:minTs/:maxTs                controllers.AdminController.deleteAllEdges(zkAddr, tableName, minTs: Long, maxTs: Long)
+#POST   /admin/swapLabel/:oldLabelName/:newLabelName                            controllers.AdminController.swapLabel(oldLabelName, newLabelName)
+#GET    /admin/reloadLabel/:labelName                                           controllers.AdminController.reloadLabel(labelName)
+#POST        /admin/getEdges                                                              controllers.AdminController.getEdges()
+POST        /graphs/copyLabel/:oldLabelName/:newLabelName                 controllers.AdminController.copyLabel(oldLabelName, newLabelName)
+POST        /graphs/renameLabel/:oldLabelName/:newLabelName               controllers.AdminController.renameLabel(oldLabelName, newLabelName)
+POST        /graphs/updateHTable/:labelName/:newHTableName                controllers.AdminController.updateHTable(labelName, newHTableName)
+PUT         /graphs/loadCache                                             controllers.AdminController.loadCache()
+
+
+# Counter Admin API
+POST    /counter/v1/:service/:action                                    controllers.CounterController.createAction(service, action)
+GET     /counter/v1/:service/:action                                    controllers.CounterController.getAction(service, action)
+PUT     /counter/v1/:service/:action                                    controllers.CounterController.updateAction(service, action)
+PUT     /counter/v1/:service/:action/prepare                            controllers.CounterController.prepareAction(service, action)
+DELETE  /counter/v1/:service/:action                                    controllers.CounterController.deleteAction(service, action)
+
+# Counter API
+GET     /counter/v1/:service/:action/ranking                            controllers.CounterController.getRankingCountAsync(service, action)
+DELETE  /counter/v1/:service/:action/ranking                            controllers.CounterController.deleteRankingCount(service, action)
+GET     /counter/v1/:service/:action/:item                              controllers.CounterController.getExactCountAsync(service, action, item)
+PUT     /counter/v1/:service/:action/:item                              controllers.CounterController.incrementCount(service, action, item)
+POST    /counter/v1/mget                                                controllers.CounterController.getExactCountAsyncMulti()
+
+# Experiment API
+POST        /graphs/experiment/:accessToken/:experimentName/:uuid         controllers.ExperimentController.experiment(accessToken, experimentName, uuid)

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/s2rest_play/conf/test.conf
----------------------------------------------------------------------
diff --git a/s2rest_play/conf/test.conf b/s2rest_play/conf/test.conf
new file mode 100644
index 0000000..c51baef
--- /dev/null
+++ b/s2rest_play/conf/test.conf
@@ -0,0 +1,2 @@
+max.retry.number=10000
+hbase.fail.prob=0.1

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/s2rest_play/test/benchmark/BenchmarkCommon.scala
----------------------------------------------------------------------
diff --git a/s2rest_play/test/benchmark/BenchmarkCommon.scala b/s2rest_play/test/benchmark/BenchmarkCommon.scala
new file mode 100644
index 0000000..9dd69ec
--- /dev/null
+++ b/s2rest_play/test/benchmark/BenchmarkCommon.scala
@@ -0,0 +1,15 @@
+package benchmark
+
+import org.specs2.mutable.Specification
+
+trait BenchmarkCommon extends Specification {
+  val wrapStr = s"\n=================================================="
+
+  def duration[T](prefix: String = "")(block: => T) = {
+    val startTs = System.currentTimeMillis()
+    val ret = block
+    val endTs = System.currentTimeMillis()
+    println(s"$wrapStr\n$prefix: took ${endTs - startTs} ms$wrapStr")
+    ret
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/s2rest_play/test/benchmark/GraphUtilSpec.scala
----------------------------------------------------------------------
diff --git a/s2rest_play/test/benchmark/GraphUtilSpec.scala b/s2rest_play/test/benchmark/GraphUtilSpec.scala
new file mode 100644
index 0000000..b5ce93a
--- /dev/null
+++ b/s2rest_play/test/benchmark/GraphUtilSpec.scala
@@ -0,0 +1,125 @@
+package benchmark
+
+import com.kakao.s2graph.core.{Management, GraphUtil}
+import com.kakao.s2graph.core.types.{SourceVertexId, HBaseType, InnerVal, VertexId}
+import org.apache.hadoop.hbase.util.Bytes
+import play.api.test.{FakeApplication, PlaySpecification}
+
+import scala.collection.mutable
+import scala.collection.mutable.ListBuffer
+import scala.util.Random
+
+class GraphUtilSpec extends BenchmarkCommon with PlaySpecification {
+
+  def between(bytes: Array[Byte], startKey: Array[Byte], endKey: Array[Byte]): Boolean =
+    Bytes.compareTo(startKey, bytes) <= 0 && Bytes.compareTo(endKey, bytes) >= 0
+
+  def betweenShort(value: Short, start: Short, end: Short): Boolean =
+    start <= value && value <= end
+
+
+  "GraphUtil" should {
+    "test murmur3 hash function distribution" in {
+      val testNum = 1000000
+      val bucketSize = Short.MaxValue / 40
+      val countsNew = new mutable.HashMap[Int, Int]()
+      val counts = new mutable.HashMap[Int, Int]()
+      for {
+        i <- (0 until testNum)
+      } {
+        val h = GraphUtil.murmur3(i.toString) / bucketSize
+        val hNew = GraphUtil.murmur3Int(i.toString) / bucketSize
+        counts += (h -> (counts.getOrElse(h, 0) + 1))
+        countsNew += (hNew -> (countsNew.getOrElse(hNew, 0) + 1))
+      }
+      val all = counts.toList.sortBy { case (bucket, count) => count }.reverse
+      val allNew = countsNew.toList.sortBy { case (bucket, count) => count }.reverse
+      val top = all.take(10)
+      val bottom = all.takeRight(10)
+      val topNew = allNew.take(10)
+      val bottomNew = allNew.takeRight(10)
+      println(s"Top: $top")
+      println(s"Bottom: $bottom")
+      println("-" * 50)
+      println(s"TopNew: $topNew")
+      println(s"Bottom: $bottomNew")
+      true
+    }
+
+    "test murmur hash skew2" in {
+      running(FakeApplication()) {
+        import HBaseType._
+        val testNum = 1000000L
+        val regionCount = 40
+        val window = Int.MaxValue / regionCount
+        val rangeBytes = new ListBuffer[(List[Byte], List[Byte])]()
+        for {
+          i <- (0 until regionCount)
+        } yield {
+          val startKey =  Bytes.toBytes(i * window)
+          val endKey = Bytes.toBytes((i + 1) * window)
+          rangeBytes += (startKey.toList -> endKey.toList)
+        }
+
+
+
+        val stats = new collection.mutable.HashMap[Int, ((List[Byte], List[Byte]), Long)]()
+        val counts = new collection.mutable.HashMap[Short, Long]()
+        stats += (0 -> (rangeBytes.head -> 0L))
+
+        for (i <- (0L until testNum)) {
+          val vertexId = SourceVertexId(DEFAULT_COL_ID, InnerVal.withLong(i, HBaseType.DEFAULT_VERSION))
+          val bytes = vertexId.bytes
+          val shortKey = GraphUtil.murmur3(vertexId.innerId.toIdString())
+          val shortVal = counts.getOrElse(shortKey, 0L) + 1L
+          counts += (shortKey -> shortVal)
+          var j = 0
+          var found = false
+          while (j < rangeBytes.size && !found) {
+            val (start, end) = rangeBytes(j)
+            if (between(bytes, start.toArray, end.toArray)) {
+              found = true
+            }
+            j += 1
+          }
+          val head = rangeBytes(j - 1)
+          val key = j - 1
+          val value = stats.get(key) match {
+            case None => 0L
+            case Some(v) => v._2 + 1
+          }
+          stats += (key -> (head, value))
+        }
+        val sorted = stats.toList.sortBy(kv => kv._2._2).reverse
+        println(s"Index: StartBytes ~ EndBytes\tStartShortBytes ~ EndShortBytes\tStartShort ~ EndShort\tCount\tShortCount")
+        sorted.foreach { case (idx, ((start, end), cnt)) =>
+          val startShort = Bytes.toShort(start.take(2).toArray)
+          val endShort = Bytes.toShort(end.take(2).toArray)
+          val count = counts.count(t => startShort <= t._1 && t._1 < endShort)
+          println(s"$idx: $start ~ $end\t${start.take(2)} ~ ${end.take(2)}\t$startShort ~ $endShort\t$cnt\t$count")
+
+        }
+        println("\n" * 10)
+        println(s"Index: StartBytes ~ EndBytes\tStartShortBytes ~ EndShortBytes\tStartShort ~ EndShort\tCount\tShortCount")
+        stats.toList.sortBy(kv => kv._1).reverse.foreach { case (idx, ((start, end), cnt)) =>
+          val startShort = Bytes.toShort(start.take(2).toArray)
+          val endShort = Bytes.toShort(end.take(2).toArray)
+          val count = counts.count(t => startShort <= t._1 && t._1 < endShort)
+          println(s"$idx: $start ~ $end\t${start.take(2)} ~ ${end.take(2)}\t$startShort ~ $endShort\t$cnt\t$count")
+
+        }
+      }
+      true
+    }
+
+    "Bytes compareTo" in {
+      val x = Array[Byte](11, -12, -26, -14, -23)
+      val startKey = Array[Byte](0, 0, 0, 0)
+      val endKey = Array[Byte](12, -52, -52, -52)
+      println(Bytes.compareTo(startKey, x))
+      println(Bytes.compareTo(endKey, x))
+      true
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/s2rest_play/test/benchmark/JsonBenchmarkSpec.scala
----------------------------------------------------------------------
diff --git a/s2rest_play/test/benchmark/JsonBenchmarkSpec.scala b/s2rest_play/test/benchmark/JsonBenchmarkSpec.scala
new file mode 100644
index 0000000..bf24ed7
--- /dev/null
+++ b/s2rest_play/test/benchmark/JsonBenchmarkSpec.scala
@@ -0,0 +1,46 @@
+package benchmark
+
+import play.api.libs.json.JsNumber
+import play.api.test.{FakeApplication, PlaySpecification, WithApplication}
+import play.libs.Json
+
+class JsonBenchmarkSpec extends BenchmarkCommon with PlaySpecification {
+  "to json" should {
+    implicit val app = FakeApplication()
+
+    "json benchmark" in new WithApplication(app) {
+
+      duration("map to json") {
+        (0 to 100) foreach { n =>
+          val numberMaps = (0 to 100).map { n => (n.toString -> JsNumber(n * n)) }.toMap
+          Json.toJson(numberMaps)
+        }
+      }
+
+      duration("directMakeJson") {
+        (0 to 100) foreach { n =>
+          var jsObj = play.api.libs.json.Json.obj()
+          (0 to 100).foreach { n =>
+            jsObj += (n.toString -> JsNumber(n * n))
+          }
+        }
+      }
+
+      duration("map to json 2") {
+        (0 to 500) foreach { n =>
+          val numberMaps = (0 to 100).map { n => (n.toString -> JsNumber(n * n)) }.toMap
+          Json.toJson(numberMaps)
+        }
+      }
+
+      duration("directMakeJson 2") {
+        (0 to 500) foreach { n =>
+          var jsObj = play.api.libs.json.Json.obj()
+          (0 to 100).foreach { n =>
+            jsObj += (n.toString -> JsNumber(n * n))
+          }
+        }
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/s2rest_play/test/benchmark/OrderingUtilBenchmarkSpec.scala
----------------------------------------------------------------------
diff --git a/s2rest_play/test/benchmark/OrderingUtilBenchmarkSpec.scala b/s2rest_play/test/benchmark/OrderingUtilBenchmarkSpec.scala
new file mode 100644
index 0000000..d38ff5e
--- /dev/null
+++ b/s2rest_play/test/benchmark/OrderingUtilBenchmarkSpec.scala
@@ -0,0 +1,103 @@
+package benchmark
+
+import com.kakao.s2graph.core.OrderingUtil._
+import com.kakao.s2graph.core.SeqMultiOrdering
+import play.api.libs.json.{JsNumber, JsValue}
+import play.api.test.PlaySpecification
+import play.api.{Application => PlayApplication}
+
+import scala.util.Random
+
+/**
+  * Created by hsleep(honeysleep@gmail.com) on 2015. 11. 9..
+  */
+class OrderingUtilBenchmarkSpec extends BenchmarkCommon with PlaySpecification {
+  "OrderingUtilBenchmarkSpec" should {
+
+    "performance MultiOrdering any" >> {
+      val tupLs = (0 until 10) map { i =>
+        Random.nextDouble() -> Random.nextLong()
+      }
+
+      val seqLs = tupLs.map { tup =>
+        Seq(tup._1, tup._2)
+      }
+
+      val sorted1 = duration("TupleOrdering double,long") {
+        (0 until 10000) foreach { _ =>
+          tupLs.sortBy { case (x, y) =>
+            -x -> -y
+          }
+        }
+        tupLs.sortBy { case (x, y) =>
+          -x -> -y
+        }
+      }.map { x => x._1 }
+
+      val sorted2 = duration("MultiOrdering double,long") {
+        (0 until 10000) foreach { _ =>
+          seqLs.sorted(new SeqMultiOrdering[Any](Seq(false, false)))
+        }
+        seqLs.sorted(new SeqMultiOrdering[Any](Seq(false, false)))
+      }.map { x => x.head }
+
+      sorted1.toString() must_== sorted2.toString()
+    }
+
+    "performance MultiOrdering double" >> {
+      val tupLs = (0 until 500) map { i =>
+        Random.nextDouble() -> Random.nextDouble()
+      }
+
+      val seqLs = tupLs.map { tup =>
+        Seq(tup._1, tup._2)
+      }
+
+      duration("MultiOrdering double") {
+        (0 until 10000) foreach { _ =>
+          seqLs.sorted(new SeqMultiOrdering[Double](Seq(false, false)))
+        }
+      }
+
+      duration("TupleOrdering double") {
+        (0 until 10000) foreach { _ =>
+          tupLs.sortBy { case (x, y) =>
+            -x -> -y
+          }
+        }
+      }
+
+      1 must_== 1
+    }
+
+    "performance MultiOrdering jsvalue" >> {
+      val tupLs = (0 until 500) map { i =>
+        Random.nextDouble() -> Random.nextLong()
+      }
+
+      val seqLs = tupLs.map { tup =>
+        Seq(JsNumber(tup._1), JsNumber(tup._2))
+      }
+
+      val sorted1 = duration("TupleOrdering double,long") {
+        (0 until 10000) foreach { _ =>
+          tupLs.sortBy { case (x, y) =>
+            -x -> -y
+          }
+        }
+        tupLs.sortBy { case (x, y) =>
+          -x -> -y
+        }
+      }
+
+      val sorted2 = duration("MultiOrdering jsvalue") {
+        (0 until 10000) foreach { _ =>
+          seqLs.sorted(new SeqMultiOrdering[JsValue](Seq(false, false)))
+        }
+        seqLs.sorted(new SeqMultiOrdering[JsValue](Seq(false, false)))
+      }
+
+      1 must_== 1
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/s2rest_play/test/benchmark/SamplingBenchmarkSpec.scala
----------------------------------------------------------------------
diff --git a/s2rest_play/test/benchmark/SamplingBenchmarkSpec.scala b/s2rest_play/test/benchmark/SamplingBenchmarkSpec.scala
new file mode 100644
index 0000000..0c27a2a
--- /dev/null
+++ b/s2rest_play/test/benchmark/SamplingBenchmarkSpec.scala
@@ -0,0 +1,85 @@
+package benchmark
+import play.api.test.{FakeApplication, PlaySpecification, WithApplication}
+import scala.annotation.tailrec
+import scala.util.Random
+
+class SamplingBenchmarkSpec extends BenchmarkCommon with PlaySpecification {
+  "sample" should {
+    implicit val app = FakeApplication()
+
+    "sample benchmark" in new WithApplication(app) {
+      @tailrec
+      def randomInt(n: Int, range: Int, set: Set[Int] = Set.empty[Int]): Set[Int] = {
+        if (set.size == n) set
+        else randomInt(n, range, set + Random.nextInt(range))
+      }
+
+      // sample using random array
+      def randomArraySample[T](num: Int, ls: List[T]): List[T] = {
+        val randomNum = randomInt(num, ls.size)
+        var sample = List.empty[T]
+        var idx = 0
+        ls.foreach { e =>
+          if (randomNum.contains(idx)) sample = e :: sample
+          idx += 1
+        }
+        sample
+      }
+
+      // sample using shuffle
+      def shuffleSample[T](num: Int, ls: List[T]): List[T] = {
+        Random.shuffle(ls).take(num)
+      }
+
+      // sample using random number generation
+      def rngSample[T](num: Int, ls: List[T]): List[T] = {
+        var sampled = List.empty[T]
+        val N = ls.size // population
+        var t = 0 // total input records dealt with
+        var m = 0 // number of items selected so far
+
+        while (m < num) {
+          val u = Random.nextDouble()
+          if ( (N - t)*u < num - m) {
+            sampled = ls(t) :: sampled
+            m += 1
+          }
+          t += 1
+        }
+        sampled
+      }
+
+      // test data
+      val testLimit = 500000
+      val testNum = 10
+      val testData = (0 to 1000).toList
+
+      // dummy for warm-up
+      (0 to testLimit) foreach { n =>
+        randomArraySample(testNum, testData)
+        shuffleSample(testNum, testData)
+        rngSample(testNum, testData)
+      }
+
+      duration("Random Array Sampling") {
+        (0 to testLimit) foreach { _ =>
+          val sampled = randomArraySample(testNum, testData)
+        }
+      }
+
+      duration("Shuffle Sampling") {
+        (0 to testLimit) foreach { _ =>
+          val sampled = shuffleSample(testNum, testData)
+        }
+      }
+
+      duration("RNG Sampling") {
+        (0 to testLimit) foreach { _ =>
+          val sampled = rngSample(testNum, testData)
+        }
+      }
+    }
+
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/s2rest_play/test/controllers/PostProcessSpec.scala
----------------------------------------------------------------------
diff --git a/s2rest_play/test/controllers/PostProcessSpec.scala b/s2rest_play/test/controllers/PostProcessSpec.scala
new file mode 100644
index 0000000..cea132a
--- /dev/null
+++ b/s2rest_play/test/controllers/PostProcessSpec.scala
@@ -0,0 +1,112 @@
+package controllers
+
+import com.kakao.s2graph.core.{OrderingUtil, SeqMultiOrdering}
+import play.api.libs.json.{JsNumber, JsString, JsValue}
+import play.api.test.PlaySpecification
+
+class PostProcessSpec extends PlaySpecification {
+  import OrderingUtil._
+
+  "test order by json" >> {
+    val jsLs: Seq[Seq[JsValue]] = Seq(
+      Seq(JsNumber(0), JsString("a")),
+      Seq(JsNumber(0), JsString("b")),
+      Seq(JsNumber(1), JsString("a")),
+      Seq(JsNumber(1), JsString("b")),
+      Seq(JsNumber(2), JsString("c"))
+    )
+
+    // number descending, string ascending
+    val sortedJsLs: Seq[Seq[JsValue]] = Seq(
+      Seq(JsNumber(2), JsString("c")),
+      Seq(JsNumber(1), JsString("a")),
+      Seq(JsNumber(1), JsString("b")),
+      Seq(JsNumber(0), JsString("a")),
+      Seq(JsNumber(0), JsString("b"))
+    )
+
+    val orderParam: Seq[Boolean] = Seq(false, true)
+    val resultJsLs = jsLs.sorted(new Ordering[Seq[JsValue]] {
+      override def compare(x: Seq[JsValue], y: Seq[JsValue]): Int = {
+        val xe = x.iterator
+        val ye = y.iterator
+        val oe = orderParam.iterator
+
+        while (xe.hasNext && ye.hasNext && oe.hasNext) {
+          val (xev, yev) = oe.next() match {
+            case true => xe.next() -> ye.next()
+            case false => ye.next() -> xe.next()
+          }
+          val res = (xev, yev) match {
+            case (JsNumber(xv), JsNumber(yv)) =>
+              Ordering[BigDecimal].compare(xv, yv)
+            case (JsString(xv), JsString(yv)) =>
+              Ordering[String].compare(xv, yv)
+            case _ => throw new Exception("type mismatch")
+          }
+          if (res != 0) return res
+        }
+
+        Ordering.Boolean.compare(xe.hasNext, ye.hasNext)
+      }
+    })
+
+    resultJsLs.toString() must_== sortedJsLs.toString
+  }
+
+  "test order by primitive type" >> {
+    val jsLs: Seq[Seq[Any]] = Seq(
+      Seq(0, "a"),
+      Seq(0, "b"),
+      Seq(1, "a"),
+      Seq(1, "b"),
+      Seq(2, "c")
+    )
+
+    // number descending, string ascending
+    val sortedJsLs: Seq[Seq[Any]] = Seq(
+      Seq(2, "c"),
+      Seq(1, "a"),
+      Seq(1, "b"),
+      Seq(0, "a"),
+      Seq(0, "b")
+    )
+
+    val ascendingLs: Seq[Boolean] = Seq(false, true)
+    val resultJsLs = jsLs.sorted(new SeqMultiOrdering[Any](ascendingLs))
+
+    resultJsLs.toString() must_== sortedJsLs.toString
+  }
+
+  "test order by primitive type with short ascending list" >> {
+    val jsLs: Seq[Seq[Any]] = Seq(
+      Seq(0, "a"),
+      Seq(1, "b"),
+      Seq(0, "b"),
+      Seq(1, "a"),
+      Seq(2, "c"),
+      Seq(1, "c"),
+      Seq(1, "d"),
+      Seq(1, "f"),
+      Seq(1, "e")
+    )
+
+    // number descending, string ascending(default)
+    val sortedJsLs: Seq[Seq[Any]] = Seq(
+      Seq(2, "c"),
+      Seq(1, "a"),
+      Seq(1, "b"),
+      Seq(1, "c"),
+      Seq(1, "d"),
+      Seq(1, "e"),
+      Seq(1, "f"),
+      Seq(0, "a"),
+      Seq(0, "b")
+    )
+
+    val ascendingLs: Seq[Boolean] = Seq(false)
+    val resultJsLs = jsLs.sorted(new SeqMultiOrdering[Any](ascendingLs))
+
+    resultJsLs.toString() must_== sortedJsLs.toString
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/test/benchmark/BenchmarkCommon.scala
----------------------------------------------------------------------
diff --git a/test/benchmark/BenchmarkCommon.scala b/test/benchmark/BenchmarkCommon.scala
deleted file mode 100644
index cd465e8..0000000
--- a/test/benchmark/BenchmarkCommon.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package benchmark
-
-import org.specs2.mutable.Specification
-
-/**
-  * Created by hsleep(honeysleep@gmail.com) on 2015. 11. 6..
-  */
-trait BenchmarkCommon extends Specification {
-  val wrapStr = s"\n=================================================="
-
-  def duration[T](prefix: String = "")(block: => T) = {
-    val startTs = System.currentTimeMillis()
-    val ret = block
-    val endTs = System.currentTimeMillis()
-    println(s"$wrapStr\n$prefix: took ${endTs - startTs} ms$wrapStr")
-    ret
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/test/benchmark/GraphUtilSpec.scala
----------------------------------------------------------------------
diff --git a/test/benchmark/GraphUtilSpec.scala b/test/benchmark/GraphUtilSpec.scala
deleted file mode 100644
index b5ce93a..0000000
--- a/test/benchmark/GraphUtilSpec.scala
+++ /dev/null
@@ -1,125 +0,0 @@
-package benchmark
-
-import com.kakao.s2graph.core.{Management, GraphUtil}
-import com.kakao.s2graph.core.types.{SourceVertexId, HBaseType, InnerVal, VertexId}
-import org.apache.hadoop.hbase.util.Bytes
-import play.api.test.{FakeApplication, PlaySpecification}
-
-import scala.collection.mutable
-import scala.collection.mutable.ListBuffer
-import scala.util.Random
-
-class GraphUtilSpec extends BenchmarkCommon with PlaySpecification {
-
-  def between(bytes: Array[Byte], startKey: Array[Byte], endKey: Array[Byte]): Boolean =
-    Bytes.compareTo(startKey, bytes) <= 0 && Bytes.compareTo(endKey, bytes) >= 0
-
-  def betweenShort(value: Short, start: Short, end: Short): Boolean =
-    start <= value && value <= end
-
-
-  "GraphUtil" should {
-    "test murmur3 hash function distribution" in {
-      val testNum = 1000000
-      val bucketSize = Short.MaxValue / 40
-      val countsNew = new mutable.HashMap[Int, Int]()
-      val counts = new mutable.HashMap[Int, Int]()
-      for {
-        i <- (0 until testNum)
-      } {
-        val h = GraphUtil.murmur3(i.toString) / bucketSize
-        val hNew = GraphUtil.murmur3Int(i.toString) / bucketSize
-        counts += (h -> (counts.getOrElse(h, 0) + 1))
-        countsNew += (hNew -> (countsNew.getOrElse(hNew, 0) + 1))
-      }
-      val all = counts.toList.sortBy { case (bucket, count) => count }.reverse
-      val allNew = countsNew.toList.sortBy { case (bucket, count) => count }.reverse
-      val top = all.take(10)
-      val bottom = all.takeRight(10)
-      val topNew = allNew.take(10)
-      val bottomNew = allNew.takeRight(10)
-      println(s"Top: $top")
-      println(s"Bottom: $bottom")
-      println("-" * 50)
-      println(s"TopNew: $topNew")
-      println(s"Bottom: $bottomNew")
-      true
-    }
-
-    "test murmur hash skew2" in {
-      running(FakeApplication()) {
-        import HBaseType._
-        val testNum = 1000000L
-        val regionCount = 40
-        val window = Int.MaxValue / regionCount
-        val rangeBytes = new ListBuffer[(List[Byte], List[Byte])]()
-        for {
-          i <- (0 until regionCount)
-        } yield {
-          val startKey =  Bytes.toBytes(i * window)
-          val endKey = Bytes.toBytes((i + 1) * window)
-          rangeBytes += (startKey.toList -> endKey.toList)
-        }
-
-
-
-        val stats = new collection.mutable.HashMap[Int, ((List[Byte], List[Byte]), Long)]()
-        val counts = new collection.mutable.HashMap[Short, Long]()
-        stats += (0 -> (rangeBytes.head -> 0L))
-
-        for (i <- (0L until testNum)) {
-          val vertexId = SourceVertexId(DEFAULT_COL_ID, InnerVal.withLong(i, HBaseType.DEFAULT_VERSION))
-          val bytes = vertexId.bytes
-          val shortKey = GraphUtil.murmur3(vertexId.innerId.toIdString())
-          val shortVal = counts.getOrElse(shortKey, 0L) + 1L
-          counts += (shortKey -> shortVal)
-          var j = 0
-          var found = false
-          while (j < rangeBytes.size && !found) {
-            val (start, end) = rangeBytes(j)
-            if (between(bytes, start.toArray, end.toArray)) {
-              found = true
-            }
-            j += 1
-          }
-          val head = rangeBytes(j - 1)
-          val key = j - 1
-          val value = stats.get(key) match {
-            case None => 0L
-            case Some(v) => v._2 + 1
-          }
-          stats += (key -> (head, value))
-        }
-        val sorted = stats.toList.sortBy(kv => kv._2._2).reverse
-        println(s"Index: StartBytes ~ EndBytes\tStartShortBytes ~ EndShortBytes\tStartShort ~ EndShort\tCount\tShortCount")
-        sorted.foreach { case (idx, ((start, end), cnt)) =>
-          val startShort = Bytes.toShort(start.take(2).toArray)
-          val endShort = Bytes.toShort(end.take(2).toArray)
-          val count = counts.count(t => startShort <= t._1 && t._1 < endShort)
-          println(s"$idx: $start ~ $end\t${start.take(2)} ~ ${end.take(2)}\t$startShort ~ $endShort\t$cnt\t$count")
-
-        }
-        println("\n" * 10)
-        println(s"Index: StartBytes ~ EndBytes\tStartShortBytes ~ EndShortBytes\tStartShort ~ EndShort\tCount\tShortCount")
-        stats.toList.sortBy(kv => kv._1).reverse.foreach { case (idx, ((start, end), cnt)) =>
-          val startShort = Bytes.toShort(start.take(2).toArray)
-          val endShort = Bytes.toShort(end.take(2).toArray)
-          val count = counts.count(t => startShort <= t._1 && t._1 < endShort)
-          println(s"$idx: $start ~ $end\t${start.take(2)} ~ ${end.take(2)}\t$startShort ~ $endShort\t$cnt\t$count")
-
-        }
-      }
-      true
-    }
-
-    "Bytes compareTo" in {
-      val x = Array[Byte](11, -12, -26, -14, -23)
-      val startKey = Array[Byte](0, 0, 0, 0)
-      val endKey = Array[Byte](12, -52, -52, -52)
-      println(Bytes.compareTo(startKey, x))
-      println(Bytes.compareTo(endKey, x))
-      true
-    }
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/test/benchmark/JsonBenchmarkSpec.scala
----------------------------------------------------------------------
diff --git a/test/benchmark/JsonBenchmarkSpec.scala b/test/benchmark/JsonBenchmarkSpec.scala
deleted file mode 100644
index bf24ed7..0000000
--- a/test/benchmark/JsonBenchmarkSpec.scala
+++ /dev/null
@@ -1,46 +0,0 @@
-package benchmark
-
-import play.api.libs.json.JsNumber
-import play.api.test.{FakeApplication, PlaySpecification, WithApplication}
-import play.libs.Json
-
-class JsonBenchmarkSpec extends BenchmarkCommon with PlaySpecification {
-  "to json" should {
-    implicit val app = FakeApplication()
-
-    "json benchmark" in new WithApplication(app) {
-
-      duration("map to json") {
-        (0 to 100) foreach { n =>
-          val numberMaps = (0 to 100).map { n => (n.toString -> JsNumber(n * n)) }.toMap
-          Json.toJson(numberMaps)
-        }
-      }
-
-      duration("directMakeJson") {
-        (0 to 100) foreach { n =>
-          var jsObj = play.api.libs.json.Json.obj()
-          (0 to 100).foreach { n =>
-            jsObj += (n.toString -> JsNumber(n * n))
-          }
-        }
-      }
-
-      duration("map to json 2") {
-        (0 to 500) foreach { n =>
-          val numberMaps = (0 to 100).map { n => (n.toString -> JsNumber(n * n)) }.toMap
-          Json.toJson(numberMaps)
-        }
-      }
-
-      duration("directMakeJson 2") {
-        (0 to 500) foreach { n =>
-          var jsObj = play.api.libs.json.Json.obj()
-          (0 to 100).foreach { n =>
-            jsObj += (n.toString -> JsNumber(n * n))
-          }
-        }
-      }
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/test/benchmark/OrderingUtilBenchmarkSpec.scala
----------------------------------------------------------------------
diff --git a/test/benchmark/OrderingUtilBenchmarkSpec.scala b/test/benchmark/OrderingUtilBenchmarkSpec.scala
deleted file mode 100644
index d38ff5e..0000000
--- a/test/benchmark/OrderingUtilBenchmarkSpec.scala
+++ /dev/null
@@ -1,103 +0,0 @@
-package benchmark
-
-import com.kakao.s2graph.core.OrderingUtil._
-import com.kakao.s2graph.core.SeqMultiOrdering
-import play.api.libs.json.{JsNumber, JsValue}
-import play.api.test.PlaySpecification
-import play.api.{Application => PlayApplication}
-
-import scala.util.Random
-
-/**
-  * Created by hsleep(honeysleep@gmail.com) on 2015. 11. 9..
-  */
-class OrderingUtilBenchmarkSpec extends BenchmarkCommon with PlaySpecification {
-  "OrderingUtilBenchmarkSpec" should {
-
-    "performance MultiOrdering any" >> {
-      val tupLs = (0 until 10) map { i =>
-        Random.nextDouble() -> Random.nextLong()
-      }
-
-      val seqLs = tupLs.map { tup =>
-        Seq(tup._1, tup._2)
-      }
-
-      val sorted1 = duration("TupleOrdering double,long") {
-        (0 until 10000) foreach { _ =>
-          tupLs.sortBy { case (x, y) =>
-            -x -> -y
-          }
-        }
-        tupLs.sortBy { case (x, y) =>
-          -x -> -y
-        }
-      }.map { x => x._1 }
-
-      val sorted2 = duration("MultiOrdering double,long") {
-        (0 until 10000) foreach { _ =>
-          seqLs.sorted(new SeqMultiOrdering[Any](Seq(false, false)))
-        }
-        seqLs.sorted(new SeqMultiOrdering[Any](Seq(false, false)))
-      }.map { x => x.head }
-
-      sorted1.toString() must_== sorted2.toString()
-    }
-
-    "performance MultiOrdering double" >> {
-      val tupLs = (0 until 500) map { i =>
-        Random.nextDouble() -> Random.nextDouble()
-      }
-
-      val seqLs = tupLs.map { tup =>
-        Seq(tup._1, tup._2)
-      }
-
-      duration("MultiOrdering double") {
-        (0 until 10000) foreach { _ =>
-          seqLs.sorted(new SeqMultiOrdering[Double](Seq(false, false)))
-        }
-      }
-
-      duration("TupleOrdering double") {
-        (0 until 10000) foreach { _ =>
-          tupLs.sortBy { case (x, y) =>
-            -x -> -y
-          }
-        }
-      }
-
-      1 must_== 1
-    }
-
-    "performance MultiOrdering jsvalue" >> {
-      val tupLs = (0 until 500) map { i =>
-        Random.nextDouble() -> Random.nextLong()
-      }
-
-      val seqLs = tupLs.map { tup =>
-        Seq(JsNumber(tup._1), JsNumber(tup._2))
-      }
-
-      val sorted1 = duration("TupleOrdering double,long") {
-        (0 until 10000) foreach { _ =>
-          tupLs.sortBy { case (x, y) =>
-            -x -> -y
-          }
-        }
-        tupLs.sortBy { case (x, y) =>
-          -x -> -y
-        }
-      }
-
-      val sorted2 = duration("MultiOrdering jsvalue") {
-        (0 until 10000) foreach { _ =>
-          seqLs.sorted(new SeqMultiOrdering[JsValue](Seq(false, false)))
-        }
-        seqLs.sorted(new SeqMultiOrdering[JsValue](Seq(false, false)))
-      }
-
-      1 must_== 1
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/test/benchmark/PostProcessBenchmarkSpec.scala
----------------------------------------------------------------------
diff --git a/test/benchmark/PostProcessBenchmarkSpec.scala b/test/benchmark/PostProcessBenchmarkSpec.scala
deleted file mode 100644
index 70644d6..0000000
--- a/test/benchmark/PostProcessBenchmarkSpec.scala
+++ /dev/null
@@ -1,238 +0,0 @@
-package benchmark
-
-import com.kakao.s2graph.core.mysqls.Label
-import com.kakao.s2graph.core.{Graph, Management}
-import controllers._
-import play.api.libs.json.{JsValue, Json}
-import play.api.test.{FakeApplication, FakeRequest, PlaySpecification}
-
-import scala.concurrent.Await
-import scala.concurrent.duration._
-
-/**
-  * Created by hsleep(honeysleep@gmail.com) on 2015. 11. 6..
-  */
-class PostProcessBenchmarkSpec extends SpecCommon with BenchmarkCommon with PlaySpecification {
-  sequential
-
-  import Helper._
-
-  init()
-
-  override def init() = {
-    running(FakeApplication()) {
-      println("[init start]: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
-      Management.deleteService(testServiceName)
-
-      // 1. createService
-      val result = AdminController.createServiceInner(Json.parse(createService))
-      println(s">> Service created : $createService, $result")
-
-      val labelNames = Map(
-        testLabelNameWeak -> testLabelNameWeakCreate
-      )
-
-      for {
-        (labelName, create) <- labelNames
-      } {
-        Management.deleteLabel(labelName)
-        Label.findByName(labelName, useCache = false) match {
-          case None =>
-            AdminController.createLabelInner(Json.parse(create))
-          case Some(label) =>
-            println(s">> Label already exist: $create, $label")
-        }
-      }
-
-      // create edges
-      val bulkEdges: String = (0 until 500).map { i =>
-        edge"${System.currentTimeMillis()} insert e 0 $i $testLabelNameWeak"($(weight=i))
-      }.mkString("\n")
-
-      val jsResult = contentAsJson(EdgeController.mutateAndPublish(bulkEdges, withWait = true))
-
-      println("[init end]: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
-    }
-  }
-
-  def getEdges(queryJson: JsValue): JsValue = {
-    val ret = route(FakeRequest(POST, "/graphs/getEdges").withJsonBody(queryJson)).get
-    contentAsJson(ret)
-  }
-
-  val s2: Graph = com.kakao.s2graph.rest.Global.s2graph
-
-//  "test performance of getEdges orderBy" >> {
-//    running(FakeApplication()) {
-//      val strJs =
-//        s"""
-//           |{
-//           |  "orderBy": [
-//           |    {"score": "DESC"},
-//           |    {"timestamp": "DESC"}
-//           |  ],
-//           |  "srcVertices": [
-//           |    {
-//           |      "serviceName": "$testServiceName",
-//           |      "columnName": "$testColumnName",
-//           |      "ids": [0]
-//           |    }
-//           |  ],
-//           |  "steps": [
-//           |    {
-//           |      "step": [
-//           |        {
-//           |          "cacheTTL": 60000,
-//           |          "label": "$testLabelNameWeak",
-//           |          "offset": 0,
-//           |          "limit": -1,
-//           |          "direction": "out",
-//           |          "scoring": [
-//           |            {"weight": 1}
-//           |          ]
-//           |        }
-//           |      ]
-//           |    }
-//           |  ]
-//           |}
-//      """.stripMargin
-//
-//      object Parser extends RequestParser
-//
-//      val js = Json.parse(strJs)
-//
-//      val q = Parser.toQuery(js)
-//
-//      val queryResultLs = Await.result(s2.getEdges(q), 1 seconds)
-//
-//      val resultJs = PostProcess.toSimpleVertexArrJson(queryResultLs)
-//
-//      (resultJs \ "size").as[Int] must_== 500
-//
-//      (0 to 5) foreach { _ =>
-//        duration("toSimpleVertexArrJson new orderBy") {
-//          (0 to 1000) foreach { _ =>
-//            PostProcess.toSimpleVertexArrJson(queryResultLs, Nil)
-//          }
-//        }
-//      }
-//
-//      (resultJs \ "size").as[Int] must_== 500
-//    }
-//  }
-
-  "test performance of getEdges" >> {
-    running(FakeApplication()) {
-      val strJs =
-        s"""
-           |{
-           |  "srcVertices": [
-           |    {
-           |      "serviceName": "$testServiceName",
-           |      "columnName": "$testColumnName",
-           |      "ids": [0]
-           |    }
-           |  ],
-           |  "steps": [
-           |    {
-           |      "step": [
-           |        {
-           |          "cacheTTL": 60000,
-           |          "label": "$testLabelNameWeak",
-           |          "offset": 0,
-           |          "limit": -1,
-           |          "direction": "out",
-           |          "scoring": [
-           |            {"weight": 1}
-           |          ]
-           |        }
-           |      ]
-           |    }
-           |  ]
-           |}
-      """.stripMargin
-
-      object Parser extends RequestParser
-
-      val js = Json.parse(strJs)
-
-      val q = Parser.toQuery(js)
-
-      val queryResultLs = Await.result(s2.getEdges(q), 1 seconds)
-
-      val resultJs = PostProcess.toSimpleVertexArrJson(queryResultLs, Nil)
-
-      (0 to 5) foreach { _ =>
-        duration("toSimpleVertexArrJson new") {
-          (0 to 1000) foreach { _ =>
-            PostProcess.toSimpleVertexArrJson(queryResultLs, Nil)
-          }
-        }
-      }
-
-      (resultJs \ "size").as[Int] must_== 500
-    }
-  }
-
-//  "test performance of getEdges withScore=false" >> {
-//    running(FakeApplication()) {
-//      val strJs =
-//        s"""
-//           |{
-//           |  "withScore": false,
-//           |  "srcVertices": [
-//           |    {
-//           |      "serviceName": "$testServiceName",
-//           |      "columnName": "$testColumnName",
-//           |      "ids": [0]
-//           |    }
-//           |  ],
-//           |  "steps": [
-//           |    {
-//           |      "step": [
-//           |        {
-//           |          "cacheTTL": 60000,
-//           |          "label": "$testLabelNameWeak",
-//           |          "offset": 0,
-//           |          "limit": -1,
-//           |          "direction": "out",
-//           |          "scoring": [
-//           |            {"weight": 1}
-//           |          ]
-//           |        }
-//           |      ]
-//           |    }
-//           |  ]
-//           |}
-//      """.stripMargin
-//
-//      object Parser extends RequestParser
-//
-//      val js = Json.parse(strJs)
-//
-//      val q = Parser.toQuery(js)
-//
-//      val queryResultLs = Await.result(s2.getEdges(q), 1 seconds)
-//
-//      val resultJs = PostProcess.toSimpleVertexArrJson(queryResultLs)
-//
-//      (resultJs \ "size").as[Int] must_== 500
-//
-//      (0 to 5) foreach { _ =>
-//        duration("toSimpleVertexArrJson withScore=false org") {
-//          (0 to 1000) foreach { _ =>
-//            PostProcess.toSimpleVertexArrJsonOrg(queryResultLs, Nil)
-//          }
-//        }
-//
-//        duration("toSimpleVertexArrJson withScore=false new") {
-//          (0 to 1000) foreach { _ =>
-//            PostProcess.toSimpleVertexArrJson(queryResultLs, Nil)
-//          }
-//        }
-//      }
-//
-//      (resultJs \ "size").as[Int] must_== 500
-//    }
-//  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/test/benchmark/SamplingBenchmarkSpec.scala
----------------------------------------------------------------------
diff --git a/test/benchmark/SamplingBenchmarkSpec.scala b/test/benchmark/SamplingBenchmarkSpec.scala
deleted file mode 100644
index 8943a62..0000000
--- a/test/benchmark/SamplingBenchmarkSpec.scala
+++ /dev/null
@@ -1,90 +0,0 @@
-package benchmark
-
-/**
- * Created by jojo on 12/1/15.
- */
-
-import play.api.test.{FakeApplication, PlaySpecification, WithApplication}
-import scala.annotation.tailrec
-import scala.util.Random
-
-class SamplingBenchmarkSpec extends BenchmarkCommon with PlaySpecification {
-  "to json" should {
-    implicit val app = FakeApplication()
-
-    "json benchmark" in new WithApplication(app) {
-      @tailrec
-      def randomInt(n: Int, range: Int, set: Set[Int] = Set.empty[Int]): Set[Int] = {
-        if (set.size == n) set
-        else randomInt(n, range, set + Random.nextInt(range))
-      }
-
-      // sample using random array
-      def randomArraySample[T](num: Int, ls: List[T]): List[T] = {
-        val randomNum = randomInt(num, ls.size)
-        var sample = List.empty[T]
-        var idx = 0
-        ls.foreach { e =>
-          if (randomNum.contains(idx)) sample = e :: sample
-          idx += 1
-        }
-        sample
-      }
-
-      // sample using shuffle
-      def shuffleSample[T](num: Int, ls: List[T]): List[T] = {
-        Random.shuffle(ls).take(num)
-      }
-
-      // sample using random number generation
-      def rngSample[T](num: Int, ls: List[T]): List[T] = {
-        var sampled = List.empty[T]
-        val N = ls.size // population
-        var t = 0 // total input records dealt with
-        var m = 0 // number of items selected so far
-
-        while (m < num) {
-          val u = Random.nextDouble()
-          if ( (N - t)*u < num - m) {
-            sampled = ls(t) :: sampled
-            m += 1
-          }
-          t += 1
-        }
-        sampled
-      }
-
-      // test data
-      val testLimit = 500000
-      val testNum = 10
-      val testData = (0 to 1000).toList
-
-      // dummy for warm-up
-      (0 to testLimit) foreach { n =>
-        randomArraySample(testNum, testData)
-        shuffleSample(testNum, testData)
-        rngSample(testNum, testData)
-      }
-
-      duration("Random Array Sampling") {
-        (0 to testLimit) foreach { _ =>
-          val sampled = randomArraySample(testNum, testData)
-        }
-      }
-
-      duration("Shuffle Sampling") {
-        (0 to testLimit) foreach { _ =>
-          val sampled = shuffleSample(testNum, testData)
-        }
-      }
-
-      duration("RNG Sampling") {
-        (0 to testLimit) foreach { _ =>
-          val sampled = rngSample(testNum, testData)
-        }
-      }
-    }
-
-
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/test/controllers/AdminControllerSpec.scala
----------------------------------------------------------------------
diff --git a/test/controllers/AdminControllerSpec.scala b/test/controllers/AdminControllerSpec.scala
deleted file mode 100644
index e41fccb..0000000
--- a/test/controllers/AdminControllerSpec.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package controllers
-
-import com.kakao.s2graph.core.mysqls.Label
-import play.api.http.HeaderNames
-import play.api.test.Helpers._
-import play.api.test.{FakeApplication, FakeRequest}
-
-import scala.concurrent.Await
-
-/**
- * Created by mojo22jojo(hyunsung.jo@gmail.com) on 15. 10. 13..
- */
-class AdminControllerSpec extends SpecCommon {
-  init()
-  "EdgeControllerSpec" should {
-    "update htable" in {
-      running(FakeApplication()) {
-        val insertUrl = s"/graphs/updateHTable/$testLabelName/$newHTableName"
-
-        val req = FakeRequest("POST", insertUrl).withBody("").withHeaders(HeaderNames.CONTENT_TYPE -> "text/plain")
-
-        Await.result(route(req).get, HTTP_REQ_WAITING_TIME)
-        Label.findByName(testLabelName, useCache = true).get.hTableName mustEqual newHTableName
-      }
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/test/controllers/BasicCrudSpec.scala
----------------------------------------------------------------------
diff --git a/test/controllers/BasicCrudSpec.scala b/test/controllers/BasicCrudSpec.scala
deleted file mode 100644
index f4f11b4..0000000
--- a/test/controllers/BasicCrudSpec.scala
+++ /dev/null
@@ -1,251 +0,0 @@
-package controllers
-
-import com.kakao.s2graph.core.Management
-import com.kakao.s2graph.core.mysqls._
-
-//import com.kakao.s2graph.core.models._
-
-import play.api.libs.json._
-import play.api.test.Helpers._
-import play.api.test.{FakeApplication, FakeRequest}
-
-import scala.concurrent.Await
-
-
-class BasicCrudSpec extends SpecCommon {
-  sequential
-
-  var seed = 0
-  def runTC(tcNum: Int, tcString: String, opWithProps: List[(Long, String, String)], expected: Map[String, String]) = {
-    for {
-      labelName <- List(testLabelName, testLabelName2)
-      i <- 0 until NUM_OF_EACH_TEST
-    } {
-      seed += 1
-//      val srcId = ((tcNum * 1000) + i).toString
-//      val tgtId = if (labelName == testLabelName) s"${srcId + 1000 + i}" else s"${srcId + 1000 + i}abc"
-      val srcId = seed.toString
-      val tgtId = srcId
-
-      val maxTs = opWithProps.map(t => t._1).max
-
-      /** insert edges */
-      println(s"---- TC${tcNum}_init ----")
-      val bulkEdge = (for ((ts, op, props) <- opWithProps) yield {
-        List(ts, op, "e", srcId, tgtId, labelName, props).mkString("\t")
-      }).mkString("\n")
-
-      val req = EdgeController.mutateAndPublish(bulkEdge, withWait = true)
-      val res = Await.result(req, HTTP_REQ_WAITING_TIME)
-
-      res.header.status must equalTo(200)
-
-      println(s"---- TC${tcNum}_init ----")
-//      Thread.sleep(100)
-
-      for {
-        label <- Label.findByName(labelName)
-        direction <- List("out", "in")
-        cacheTTL <- List(-1L)
-      } {
-        val (serviceName, columnName, id, otherId) = direction match {
-          case "out" => (label.srcService.serviceName, label.srcColumn.columnName, srcId, tgtId)
-          case "in" => (label.tgtService.serviceName, label.tgtColumn.columnName, tgtId, srcId)
-        }
-        val qId = if (labelName == testLabelName) id else "\"" + id + "\""
-        val query = queryJson(serviceName, columnName, labelName, qId, direction, cacheTTL)
-        val ret = route(FakeRequest(POST, "/graphs/getEdges").withJsonBody(query)).get
-        val jsResult = commonCheck(ret)
-
-        val results = jsResult \ "results"
-        val deegrees = (jsResult \ "degrees").as[List[JsObject]]
-        val propsLs = (results \\ "props").seq
-        (deegrees.head \ LabelMeta.degree.name).as[Int] must equalTo(1)
-
-        val from = (results \\ "from").seq.last.toString.replaceAll("\"", "")
-        val to = (results \\ "to").seq.last.toString.replaceAll("\"", "")
-
-        from must equalTo(id.toString)
-        to must equalTo(otherId.toString)
-//        (results \\ "_timestamp").seq.last.as[Long] must equalTo(maxTs)
-        for ((key, expectedVal) <- expected) {
-          propsLs.last.as[JsObject].keys.contains(key) must equalTo(true)
-          (propsLs.last \ key).toString must equalTo(expectedVal)
-        }
-        Await.result(ret, HTTP_REQ_WAITING_TIME)
-      }
-    }
-  }
-
-  init()
-  "Basic Crud " should {
-    "tc1" in {
-      running(FakeApplication()) {
-
-        var tcNum = 0
-        var tcString = ""
-        var bulkQueries = List.empty[(Long, String, String)]
-        var expected = Map.empty[String, String]
-
-        tcNum = 7
-        tcString = "[t1 -> t2 -> t3 test case] insert(t1) delete(t2) insert(t3) test "
-        bulkQueries = List(
-          (t1, "insert", "{\"time\": 10}"),
-          (t2, "delete", ""),
-          (t3, "insert", "{\"time\": 10, \"weight\": 20}"))
-        expected = Map("time" -> "10", "weight" -> "20")
-
-        runTC(tcNum, tcString, bulkQueries, expected)
-
-        tcNum = 8
-        tcString = "[t1 -> t2 -> t3 test case] insert(t1) delete(t2) insert(t3) test "
-        bulkQueries = List(
-          (t1, "insert", "{\"time\": 10}"),
-          (t3, "insert", "{\"time\": 10, \"weight\": 20}"),
-          (t2, "delete", ""))
-        expected = Map("time" -> "10", "weight" -> "20")
-
-        runTC(tcNum, tcString, bulkQueries, expected)
-
-        tcNum = 9
-        tcString = "[t3 -> t2 -> t1 test case] insert(t3) delete(t2) insert(t1) test "
-        bulkQueries = List(
-          (t3, "insert", "{\"time\": 10, \"weight\": 20}"),
-          (t2, "delete", ""),
-          (t1, "insert", "{\"time\": 10}"))
-        expected = Map("time" -> "10", "weight" -> "20")
-
-        runTC(tcNum, tcString, bulkQueries, expected)
-
-        tcNum = 10
-        tcString = "[t3 -> t1 -> t2 test case] insert(t3) insert(t1) delete(t2) test "
-        bulkQueries = List(
-          (t3, "insert", "{\"time\": 10, \"weight\": 20}"),
-          (t1, "insert", "{\"time\": 10}"),
-          (t2, "delete", ""))
-        expected = Map("time" -> "10", "weight" -> "20")
-
-        runTC(tcNum, tcString, bulkQueries, expected)
-
-        tcNum = 11
-        tcString = "[t2 -> t1 -> t3 test case] delete(t2) insert(t1) insert(t3) test"
-        bulkQueries = List(
-          (t2, "delete", ""),
-          (t1, "insert", "{\"time\": 10}"),
-          (t3, "insert", "{\"time\": 10, \"weight\": 20}"))
-        expected = Map("time" -> "10", "weight" -> "20")
-
-        runTC(tcNum, tcString, bulkQueries, expected)
-
-        tcNum = 12
-        tcString = "[t2 -> t3 -> t1 test case] delete(t2) insert(t3) insert(t1) test "
-        bulkQueries = List(
-          (t2, "delete", ""),
-          (t3, "insert", "{\"time\": 10, \"weight\": 20}"),
-          (t1, "insert", "{\"time\": 10}"))
-        expected = Map("time" -> "10", "weight" -> "20")
-
-        runTC(tcNum, tcString, bulkQueries, expected)
-
-        tcNum = 13
-        tcString = "[t1 -> t2 -> t3 test case] update(t1) delete(t2) update(t3) test "
-        bulkQueries = List(
-          (t1, "update", "{\"time\": 10}"),
-          (t2, "delete", ""),
-          (t3, "update", "{\"time\": 10, \"weight\": 20}"))
-        expected = Map("time" -> "10", "weight" -> "20")
-
-        runTC(tcNum, tcString, bulkQueries, expected)
-        tcNum = 14
-        tcString = "[t1 -> t3 -> t2 test case] update(t1) update(t3) delete(t2) test "
-        bulkQueries = List(
-          (t1, "update", "{\"time\": 10}"),
-          (t3, "update", "{\"time\": 10, \"weight\": 20}"),
-          (t2, "delete", ""))
-        expected = Map("time" -> "10", "weight" -> "20")
-
-        runTC(tcNum, tcString, bulkQueries, expected)
-        tcNum = 15
-        tcString = "[t2 -> t1 -> t3 test case] delete(t2) update(t1) update(t3) test "
-        bulkQueries = List(
-          (t2, "delete", ""),
-          (t1, "update", "{\"time\": 10}"),
-          (t3, "update", "{\"time\": 10, \"weight\": 20}"))
-        expected = Map("time" -> "10", "weight" -> "20")
-
-        runTC(tcNum, tcString, bulkQueries, expected)
-        tcNum = 16
-        tcString = "[t2 -> t3 -> t1 test case] delete(t2) update(t3) update(t1) test"
-        bulkQueries = List(
-          (t2, "delete", ""),
-          (t3, "update", "{\"time\": 10, \"weight\": 20}"),
-          (t1, "update", "{\"time\": 10}"))
-        expected = Map("time" -> "10", "weight" -> "20")
-
-        runTC(tcNum, tcString, bulkQueries, expected)
-        tcNum = 17
-        tcString = "[t3 -> t2 -> t1 test case] update(t3) delete(t2) update(t1) test "
-        bulkQueries = List(
-          (t3, "update", "{\"time\": 10, \"weight\": 20}"),
-          (t2, "delete", ""),
-          (t1, "update", "{\"time\": 10}"))
-        expected = Map("time" -> "10", "weight" -> "20")
-
-        runTC(tcNum, tcString, bulkQueries, expected)
-        tcNum = 18
-        tcString = "[t3 -> t1 -> t2 test case] update(t3) update(t1) delete(t2) test "
-        bulkQueries = List(
-          (t3, "update", "{\"time\": 10, \"weight\": 20}"),
-          (t1, "update", "{\"time\": 10}"),
-          (t2, "delete", ""))
-        expected = Map("time" -> "10", "weight" -> "20")
-
-        runTC(tcNum, tcString, bulkQueries, expected)
-
-        tcNum = 19
-        tcString = "[t5 -> t1 -> t3 -> t2 -> t4 test case] update(t5) insert(t1) insert(t3) delete(t2) update(t4) test "
-        bulkQueries = List(
-          (t5, "update", "{\"is_blocked\": true}"),
-          (t1, "insert", "{\"is_hidden\": false}"),
-          (t3, "insert", "{\"is_hidden\": false, \"weight\": 10}"),
-          (t2, "delete", ""),
-          (t4, "update", "{\"time\": 1, \"weight\": -10}"))
-        expected = Map("time" -> "1", "weight" -> "-10", "is_hidden" -> "false", "is_blocked" -> "true")
-
-        runTC(tcNum, tcString, bulkQueries, expected)
-        true
-      }
-    }
-  }
-
-  "toLogString" in {
-    running(FakeApplication()) {
-      val bulkQueries = List(
-        ("1445240543366", "update", "{\"is_blocked\":true}"),
-        ("1445240543362", "insert", "{\"is_hidden\":false}"),
-        ("1445240543364", "insert", "{\"is_hidden\":false,\"weight\":10}"),
-        ("1445240543363", "delete", "{}"),
-        ("1445240543365", "update", "{\"time\":1, \"weight\":-10}"))
-
-      val (srcId, tgtId, labelName) = ("1", "2", testLabelName)
-
-      val bulkEdge = (for ((ts, op, props) <- bulkQueries) yield {
-        Management.toEdge(ts.toLong, op, srcId, tgtId, labelName, "out", props).toLogString
-      }).mkString("\n")
-
-      val expected = Seq(
-        Seq("1445240543366", "update", "e", "1", "2", "s2graph_label_test", "{\"is_blocked\":true}"),
-        Seq("1445240543362", "insert", "e", "1", "2", "s2graph_label_test", "{\"is_hidden\":false}"),
-        Seq("1445240543364", "insert", "e", "1", "2", "s2graph_label_test", "{\"is_hidden\":false,\"weight\":10}"),
-        Seq("1445240543363", "delete", "e", "1", "2", "s2graph_label_test"),
-        Seq("1445240543365", "update", "e", "1", "2", "s2graph_label_test", "{\"time\":1,\"weight\":-10}")
-      ).map(_.mkString("\t")).mkString("\n")
-
-      bulkEdge must equalTo(expected)
-
-      true
-    }
-  }
-}
-
-

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/test/controllers/EdgeControllerSpec.scala
----------------------------------------------------------------------
diff --git a/test/controllers/EdgeControllerSpec.scala b/test/controllers/EdgeControllerSpec.scala
deleted file mode 100644
index e76404a..0000000
--- a/test/controllers/EdgeControllerSpec.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package controllers
-
-import play.api.http.HeaderNames
-import play.api.test.{FakeApplication, FakeRequest, PlaySpecification, WithApplication}
-import play.api.{Application => PlayApplication}
-
-/**
- * Created by hsleep(honeysleep@gmail.com) on 15. 9. 1..
- */
-class EdgeControllerSpec extends PlaySpecification {
-//  "EdgeControllerSpec" should {
-//    implicit val app = FakeApplication()
-//
-//    "bad request invalid json" in new WithApplication(app) {
-//      val insertUrl = "http://localhost:9000/graphs/edges/insert"
-//      val req = FakeRequest("POST", insertUrl).withBody("").withHeaders(HeaderNames.CONTENT_TYPE -> "application/json")
-//      val result = EdgeController.inserts().apply(req).run
-//
-//      status(result) must_== BAD_REQUEST
-//    }
-//  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/test/controllers/PostProcessSpec.scala
----------------------------------------------------------------------
diff --git a/test/controllers/PostProcessSpec.scala b/test/controllers/PostProcessSpec.scala
deleted file mode 100644
index 9573791..0000000
--- a/test/controllers/PostProcessSpec.scala
+++ /dev/null
@@ -1,115 +0,0 @@
-package controllers
-
-import com.kakao.s2graph.core.SeqMultiOrdering
-import com.kakao.s2graph.core.OrderingUtil._
-import play.api.libs.json.{JsNumber, JsString, JsValue}
-import play.api.test.PlaySpecification
-
-/**
- * Created by hsleep on 2015. 11. 4..
- */
-class PostProcessSpec extends SpecCommon with PlaySpecification {
-
-  "test order by json" >> {
-    val jsLs: Seq[Seq[JsValue]] = Seq(
-      Seq(JsNumber(0), JsString("a")),
-      Seq(JsNumber(0), JsString("b")),
-      Seq(JsNumber(1), JsString("a")),
-      Seq(JsNumber(1), JsString("b")),
-      Seq(JsNumber(2), JsString("c"))
-    )
-
-    // number descending, string ascending
-    val sortedJsLs: Seq[Seq[JsValue]] = Seq(
-      Seq(JsNumber(2), JsString("c")),
-      Seq(JsNumber(1), JsString("a")),
-      Seq(JsNumber(1), JsString("b")),
-      Seq(JsNumber(0), JsString("a")),
-      Seq(JsNumber(0), JsString("b"))
-    )
-
-    val orderParam: Seq[Boolean] = Seq(false, true)
-    val resultJsLs = jsLs.sorted(new Ordering[Seq[JsValue]] {
-      override def compare(x: Seq[JsValue], y: Seq[JsValue]): Int = {
-        val xe = x.iterator
-        val ye = y.iterator
-        val oe = orderParam.iterator
-
-        while (xe.hasNext && ye.hasNext && oe.hasNext) {
-          val (xev, yev) = oe.next() match {
-            case true => xe.next() -> ye.next()
-            case false => ye.next() -> xe.next()
-          }
-          val res = (xev, yev) match {
-            case (JsNumber(xv), JsNumber(yv)) =>
-              Ordering[BigDecimal].compare(xv, yv)
-            case (JsString(xv), JsString(yv)) =>
-              Ordering[String].compare(xv, yv)
-            case _ => throw new Exception("type mismatch")
-          }
-          if (res != 0) return res
-        }
-
-        Ordering.Boolean.compare(xe.hasNext, ye.hasNext)
-      }
-    })
-
-    resultJsLs.toString() must_== sortedJsLs.toString
-  }
-
-  "test order by primitive type" >> {
-    val jsLs: Seq[Seq[Any]] = Seq(
-      Seq(0, "a"),
-      Seq(0, "b"),
-      Seq(1, "a"),
-      Seq(1, "b"),
-      Seq(2, "c")
-    )
-
-    // number descending, string ascending
-    val sortedJsLs: Seq[Seq[Any]] = Seq(
-      Seq(2, "c"),
-      Seq(1, "a"),
-      Seq(1, "b"),
-      Seq(0, "a"),
-      Seq(0, "b")
-    )
-
-    val ascendingLs: Seq[Boolean] = Seq(false, true)
-    val resultJsLs = jsLs.sorted(new SeqMultiOrdering[Any](ascendingLs))
-
-    resultJsLs.toString() must_== sortedJsLs.toString
-  }
-
-  "test order by primitive type with short ascending list" >> {
-    val jsLs: Seq[Seq[Any]] = Seq(
-      Seq(0, "a"),
-      Seq(1, "b"),
-      Seq(0, "b"),
-      Seq(1, "a"),
-      Seq(2, "c"),
-      Seq(1, "c"),
-      Seq(1, "d"),
-      Seq(1, "f"),
-      Seq(1, "e")
-    )
-
-    // number descending, string ascending(default)
-    val sortedJsLs: Seq[Seq[Any]] = Seq(
-      Seq(2, "c"),
-      Seq(1, "a"),
-      Seq(1, "b"),
-      Seq(1, "c"),
-      Seq(1, "d"),
-      Seq(1, "e"),
-      Seq(1, "f"),
-      Seq(0, "a"),
-      Seq(0, "b")
-    )
-
-    val ascendingLs: Seq[Boolean] = Seq(false)
-    val resultJsLs = jsLs.sorted(new SeqMultiOrdering[Any](ascendingLs))
-
-    resultJsLs.toString() must_== sortedJsLs.toString
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/f2311f25/test/controllers/QueryCacheSpec.scala
----------------------------------------------------------------------
diff --git a/test/controllers/QueryCacheSpec.scala b/test/controllers/QueryCacheSpec.scala
deleted file mode 100644
index 7d91aa9..0000000
--- a/test/controllers/QueryCacheSpec.scala
+++ /dev/null
@@ -1,89 +0,0 @@
-//package test.controllers
-//
-////import com.kakao.s2graph.core.models._
-//
-//import controllers.EdgeController
-//import play.api.libs.json._
-//import play.api.test.Helpers._
-//import play.api.test.{FakeApplication, FakeRequest}
-//
-//class QueryCacheSpec extends SpecCommon {
-//  init()
-//
-//  "cache test" should {
-//    def queryWithTTL(id: Int, cacheTTL: Long) = Json.parse( s"""
-//        { "srcVertices": [
-//          { "serviceName": "${testServiceName}",
-//            "columnName": "${testColumnName}",
-//            "id": ${id}
-//           }],
-//          "steps": [[ {
-//            "label": "${testLabelName}",
-//            "direction": "out",
-//            "offset": 0,
-//            "limit": 10,
-//            "cacheTTL": ${cacheTTL},
-//            "scoring": {"weight": 1} }]]
-//          }""")
-//
-//    def getEdges(queryJson: JsValue): JsValue = {
-//      var ret = route(FakeRequest(POST, "/graphs/getEdges").withJsonBody(queryJson)).get
-//      contentAsJson(ret)
-//    }
-//
-//    // init
-//    running(FakeApplication()) {
-//      // insert bulk and wait ..
-//      val bulkEdges: String = Seq(
-//        Seq("1", "insert", "e", "0", "2", "s2graph_label_test", "{}").mkString("\t"),
-//        Seq("1", "insert", "e", "1", "2", "s2graph_label_test", "{}").mkString("\t")
-//      ).mkString("\n")
-//
-//      val jsResult = contentAsJson(EdgeController.mutateAndPublish(bulkEdges, withWait = true))
-//      Thread.sleep(asyncFlushInterval)
-//    }
-//
-//    "tc1: query with {id: 0, ttl: 1000}" in {
-//      running(FakeApplication()) {
-//        var jsRslt = getEdges(queryWithTTL(0, 1000))
-//        var cacheRemain = (jsRslt \\ "cacheRemain").head
-//        cacheRemain.as[Int] must greaterThan(500)
-//
-//        // get edges from cache after wait 500ms
-//        Thread.sleep(500)
-//        val ret = route(FakeRequest(POST, "/graphs/getEdges").withJsonBody(queryWithTTL(0, 1000))).get
-//        jsRslt = contentAsJson(ret)
-//        cacheRemain = (jsRslt \\ "cacheRemain").head
-//        cacheRemain.as[Int] must lessThan(500)
-//      }
-//    }
-//
-//    "tc2: query with {id: 1, ttl: 3000}" in {
-//      running(FakeApplication()) {
-//        var jsRslt = getEdges(queryWithTTL(1, 3000))
-//        var cacheRemain = (jsRslt \\ "cacheRemain").head
-//        // before update: is_blocked is false
-//        (jsRslt \\ "is_blocked").head must equalTo(JsBoolean(false))
-//
-//        val bulkEdges = Seq(
-//          Seq("2", "update", "e", "0", "2", "s2graph_label_test", "{\"is_blocked\": true}").mkString("\t"),
-//          Seq("2", "update", "e", "1", "2", "s2graph_label_test", "{\"is_blocked\": true}").mkString("\t")
-//        ).mkString("\n")
-//
-//        // update edges with {is_blocked: true}
-//        jsRslt = contentAsJson(EdgeController.mutateAndPublish(bulkEdges, withWait = true))
-//
-//        Thread.sleep(asyncFlushInterval)
-//
-//        // prop 'is_blocked' still false, cause queryResult on cache
-//        jsRslt = getEdges(queryWithTTL(1, 3000))
-//        (jsRslt \\ "is_blocked").head must equalTo(JsBoolean(false))
-//
-//        // after wait 3000ms prop 'is_blocked' is updated to true, cache cleared
-//        Thread.sleep(3000)
-//        jsRslt = getEdges(queryWithTTL(1, 3000))
-//        (jsRslt \\ "is_blocked").head must equalTo(JsBoolean(true))
-//      }
-//    }
-//  }
-//}