<commit_before>package justin.db.client

import java.util.UUID

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.testkit.ScalatestRouteTest
import justin.db.client.HttpRouter.{PutValue, _}
import justin.db.replication.{R, W}
import justin.db.{Data, StorageNodeActorRef}
import org.scalatest.{FlatSpec, Matchers}
import spray.json.{JsString, _}

import scala.concurrent.Future

class HttpRouterTest extends FlatSpec with Matchers with ScalatestRouteTest {

  behavior of "Http Router"

  /**
    * GET part
    */
  it should "get \"OK\" http code for successful read result" in {
    val value  = "value"
    val id     = UUID.randomUUID()
    val r      = 1
    val router = new HttpRouter(getFound(Data(id, value)))

    Get(s"/get?id=${id.toString}&r=$r") ~> Route.seal(router.routes) ~> check {
      status                       shouldBe StatusCodes.OK
      responseAs[String].parseJson shouldBe JsObject("value" -> JsString(value))
    }
  }

  it should "get \"MultipleChoices\" http code for read conflicted data" in {
    val r      = 1
    val id     = UUID.randomUUID()
    val data1  = Data(id, "value-1")
    val data2  = Data(id, "value-2")
    val router = new HttpRouter(getConflicted(data1, data2))

    Get(s"/get?id=${id.toString}&r=$r") ~> Route.seal(router.routes) ~> check {
      status                       shouldBe StatusCodes.MultipleChoices
      responseAs[String].parseJson shouldBe JsObject("value" -> JsString("Multiple Choices"))
    }
  }

  it should "get \"NotFound\" http code for missed searched data" in {
    val value  = "value"
    val id     = UUID.randomUUID().toString
    val r      = 1
    val router = new HttpRouter(notFound(value))

    Get(s"/get?id=$id&r=$r") ~> Route.seal(router.routes) ~> check {
      status                       shouldBe StatusCodes.NotFound
      responseAs[String].parseJson shouldBe JsObject("value" -> JsString(s"Not found value with id $id"))
    }
  }

  it should "get \"BadRequest\" http code for unsuccessful read result" in {
    val value  = "value"
    val id     = UUID.randomUUID().toString
    val r      = 1
    val error  = "Bad Request"
    val router = new HttpRouter(badRequest(error))

    Get(s"/get?id=$id&r=$r") ~> Route.seal(router.routes) ~> check {
      status                       shouldBe StatusCodes.BadRequest
      responseAs[String].parseJson shouldBe JsObject("value" -> JsString(error))
    }
  }

  private def getFound(data: Data) = new HttpStorageNodeClient(StorageNodeActorRef(null)) {
    override def get(id: UUID, r: R): Future[GetValueResponse] = Future.successful(GetValueResponse.Found(data))
  }

  private def getConflicted(data1: Data, data2: Data) = new HttpStorageNodeClient(StorageNodeActorRef(null)) {
    override def get(id: UUID, r: R): Future[GetValueResponse] = Future.successful(GetValueResponse.Conflicted(data1, data2))
  }

  private def notFound(value: String) = new HttpStorageNodeClient(StorageNodeActorRef(null)) {
    override def get(id: UUID, r: R): Future[GetValueResponse] = Future.successful(GetValueResponse.NotFound)
  }

  private def badRequest(error: String) = new HttpStorageNodeClient(StorageNodeActorRef(null)) {
    override def get(id: UUID, r: R): Future[GetValueResponse] = Future.successful(GetValueResponse.Failure(error))
  }

  /**
    * PUT part
    */
  it should "get \"NoContent\" http code for successful write result" in {
    val putValue = PutValue(id = UUID.randomUUID(), value = "value", w = 3)
    val router   = new HttpRouter(successfulWrite(putValue))

    Post("/put", putValue) ~> Route.seal(router.routes) ~> check {
      status shouldBe StatusCodes.NoContent
    }
  }
<commit_msg>test that router responds with VectorClockHeader for Found/Conflicted results<commit_after>package justin.db.client

import java.util.UUID

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.testkit.ScalatestRouteTest
import justin.db.client.HttpRouter.{PutValue, _}
import justin.db.replication.{R, W}
import justin.db.{Data, StorageNodeActorRef}
import org.scalatest.{FlatSpec, Matchers}
import spray.json.{JsString, _}

import scala.concurrent.Future

class HttpRouterTest extends FlatSpec with Matchers with ScalatestRouteTest {

  behavior of "Http Router"

  /**
    * GET part
    */
  it should "get \"OK\" http code for successful read result" in {
    val id     = UUID.randomUUID()
    val data   = Data(id, "value")
    val r      = 1
    val router = new HttpRouter(getFound(data))

    Get(s"/get?id=${id.toString}&r=$r") ~> Route.seal(router.routes) ~> check {
      status                       shouldBe StatusCodes.OK
      responseAs[String].parseJson shouldBe JsObject("value" -> JsString(data.value))
      header[VectorClockHeader]    shouldBe Some(VectorClockHeader(data.vclock))
    }
  }

  it should "get \"MultipleChoices\" http code for read conflicted data" in {
    val r      = 1
    val id     = UUID.randomUUID()
    val data1  = Data(id, "value-1")
    val data2  = Data(id, "value-2")
    val router = new HttpRouter(getConflicted(data1, data2))

    Get(s"/get?id=${id.toString}&r=$r") ~> Route.seal(router.routes) ~> check {
      status                       shouldBe StatusCodes.MultipleChoices
      responseAs[String].parseJson shouldBe JsObject("value" -> JsString("Multiple Choices"))
      header[VectorClockHeader]    shouldBe Some(VectorClockHeader(data1.vclock)) // TODO: this is not yet true
    }
  }

  it should "get \"NotFound\" http code for missed searched data" in {
    val value  = "value"
    val id     = UUID.randomUUID().toString
    val r      = 1
    val router = new HttpRouter(notFound(value))

    Get(s"/get?id=$id&r=$r") ~> Route.seal(router.routes) ~> check {
      status                       shouldBe StatusCodes.NotFound
      responseAs[String].parseJson shouldBe JsObject("value" -> JsString(s"Not found value with id $id"))
      header[VectorClockHeader]    shouldBe None
    }
  }

  it should "get \"BadRequest\" http code for unsuccessful read result" in {
    val value  = "value"
    val id     = UUID.randomUUID().toString
    val r      = 1
    val error  = "Bad Request"
    val router = new HttpRouter(badRequest(error))

    Get(s"/get?id=$id&r=$r") ~> Route.seal(router.routes) ~> check {
      status                       shouldBe StatusCodes.BadRequest
      responseAs[String].parseJson shouldBe JsObject("value" -> JsString(error))
      header[VectorClockHeader]    shouldBe None
    }
  }

  private def getFound(data: Data) = new HttpStorageNodeClient(StorageNodeActorRef(null)) {
    override def get(id: UUID, r: R): Future[GetValueResponse] = Future.successful(GetValueResponse.Found(data))
  }

  private def getConflicted(data1: Data, data2: Data) = new HttpStorageNodeClient(StorageNodeActorRef(null)) {
    override def get(id: UUID, r: R): Future[GetValueResponse] = Future.successful(GetValueResponse.Conflicted(data1, data2))
  }

  private def notFound(value: String) = new HttpStorageNodeClient(StorageNodeActorRef(null)) {
    override def get(id: UUID, r: R): Future[GetValueResponse] = Future.successful(GetValueResponse.NotFound)
  }

  private def badRequest(error: String) = new HttpStorageNodeClient(StorageNodeActorRef(null)) {
    override def get(id: UUID, r: R): Future[GetValueResponse] = Future.successful(GetValueResponse.Failure(error))
  }

  /**
    * PUT part
    */
  it should "get \"NoContent\" http code for successful write result" in {
    val putValue = PutValue(id = UUID.randomUUID(), value = "value", w = 3)
    val router   = new HttpRouter(successfulWrite(putValue))

    Post("/put", putValue) ~> Route.seal(router.routes) ~> check {
      status shouldBe StatusCodes.NoContent
    }
  }

{'fraction_non_alphanumeric': 0.11897268034747577, 'fraction_numerical': 0.003902807503462168, 'mean_word_length': 3.415786548082268, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6442166', 'n_tokens_mistral': 2537, 'n_tokens_neox': 2504, 'n_words': 596}