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))
-// }
-// }
-// }
-//}