mirror of
https://github.com/arcan1s/ffxivbis.git
synced 2025-04-24 17:27:17 +00:00
some tests
This commit is contained in:
parent
d1001ffb8e
commit
b228595a1b
23
build.sbt
23
build.sbt
@ -1,28 +1,5 @@
|
||||
name := "ffxivbis"
|
||||
|
||||
version := "0.9.0"
|
||||
|
||||
scalaVersion := "2.13.1"
|
||||
|
||||
scalacOptions ++= Seq("-deprecation", "-feature")
|
||||
|
||||
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.3"
|
||||
libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.9.2"
|
||||
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-http" % "10.1.10"
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-http-spray-json" % "10.1.10"
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-stream" % "2.5.23"
|
||||
libraryDependencies += "com.github.swagger-akka-http" %% "swagger-akka-http" % "2.0.4"
|
||||
libraryDependencies += "javax.ws.rs" % "javax.ws.rs-api" % "2.1.1"
|
||||
|
||||
libraryDependencies += "io.spray" %% "spray-json" % "1.3.5"
|
||||
libraryDependencies += "com.lihaoyi" %% "scalatags" % "0.7.0"
|
||||
|
||||
libraryDependencies += "com.typesafe.slick" %% "slick" % "3.3.2"
|
||||
libraryDependencies += "com.typesafe.slick" %% "slick-hikaricp" % "3.3.2"
|
||||
libraryDependencies += "org.flywaydb" % "flyway-core" % "6.0.6"
|
||||
libraryDependencies += "org.xerial" % "sqlite-jdbc" % "3.28.0"
|
||||
libraryDependencies += "org.postgresql" % "postgresql" % "9.3-1104-jdbc4"
|
||||
|
||||
libraryDependencies += "org.mindrot" % "jbcrypt" % "0.3m"
|
||||
|
||||
|
19
libraries.sbt
Normal file
19
libraries.sbt
Normal file
@ -0,0 +1,19 @@
|
||||
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.3"
|
||||
libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.9.2"
|
||||
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-http" % "10.1.10"
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-http-spray-json" % "10.1.10"
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-stream" % "2.5.23"
|
||||
libraryDependencies += "com.github.swagger-akka-http" %% "swagger-akka-http" % "2.0.4"
|
||||
libraryDependencies += "javax.ws.rs" % "javax.ws.rs-api" % "2.1.1"
|
||||
|
||||
libraryDependencies += "io.spray" %% "spray-json" % "1.3.5"
|
||||
libraryDependencies += "com.lihaoyi" %% "scalatags" % "0.7.0"
|
||||
|
||||
libraryDependencies += "com.typesafe.slick" %% "slick" % "3.3.2"
|
||||
libraryDependencies += "com.typesafe.slick" %% "slick-hikaricp" % "3.3.2"
|
||||
libraryDependencies += "org.flywaydb" % "flyway-core" % "6.0.6"
|
||||
libraryDependencies += "org.xerial" % "sqlite-jdbc" % "3.28.0"
|
||||
libraryDependencies += "org.postgresql" % "postgresql" % "9.3-1104-jdbc4"
|
||||
|
||||
libraryDependencies += "org.mindrot" % "jbcrypt" % "0.3m"
|
@ -0,0 +1,36 @@
|
||||
create table players (
|
||||
party_id text not null,
|
||||
player_id bigserial,
|
||||
created bigint not null,
|
||||
nick text not null,
|
||||
job text not null,
|
||||
bis_link text,
|
||||
priority integer not null default 1);
|
||||
create unique index players_nick_job_idx on players(party_id, nick, job);
|
||||
|
||||
create table loot (
|
||||
loot_id bigserial,
|
||||
player_id bigint not null,
|
||||
created bigint not null,
|
||||
piece text not null,
|
||||
is_tome integer not null,
|
||||
job text not null,
|
||||
foreign key (player_id) references players(player_id) on delete cascade);
|
||||
create index loot_owner_idx on loot(player_id);
|
||||
|
||||
create table bis (
|
||||
player_id bigint not null,
|
||||
created bigint not null,
|
||||
piece text not null,
|
||||
is_tome integer not null,
|
||||
job text not null,
|
||||
foreign key (player_id) references players(player_id) on delete cascade);
|
||||
create unique index bis_piece_player_id_idx on bis(player_id, piece);
|
||||
|
||||
create table users (
|
||||
party_id text not null,
|
||||
user_id bigserial,
|
||||
username text not null,
|
||||
password text not null,
|
||||
permission text not null);
|
||||
create unique index users_username_idx on users(party_id, username);
|
@ -1,6 +1,6 @@
|
||||
create table players (
|
||||
party_id text not null,
|
||||
player_id integer primary key,
|
||||
player_id integer primary key autoincrement,
|
||||
created integer not null,
|
||||
nick text not null,
|
||||
job text not null,
|
||||
@ -9,7 +9,7 @@ create table players (
|
||||
create unique index players_nick_job_idx on players(party_id, nick, job);
|
||||
|
||||
create table loot (
|
||||
loot_id integer primary key,
|
||||
loot_id integer primary key autoincrement,
|
||||
player_id integer not null,
|
||||
created integer not null,
|
||||
piece text not null,
|
||||
@ -29,7 +29,7 @@ create unique index bis_piece_player_id_idx on bis(player_id, piece);
|
||||
|
||||
create table users (
|
||||
party_id text not null,
|
||||
user_id integer primary key,
|
||||
user_id integer primary key autoincrement,
|
||||
username text not null,
|
||||
password text not null,
|
||||
permission text not null);
|
5
src/main/resources/logback.xml
Normal file
5
src/main/resources/logback.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<configuration>
|
||||
|
||||
<logger name="slick.jdbc.JdbcBackend.statement" level="DEBUG" />
|
||||
|
||||
</configuration>
|
@ -22,6 +22,16 @@ me.arcanis.ffxivbis {
|
||||
}
|
||||
numThreads = 10
|
||||
}
|
||||
|
||||
postgresql {
|
||||
profile = "slick.jdbc.PostgresProfile$"
|
||||
db {
|
||||
url = "jdbc:postgresql://localhost/ffxivbis"
|
||||
user = "user"
|
||||
password = "password"
|
||||
}
|
||||
numThreads = 10
|
||||
}
|
||||
}
|
||||
|
||||
settings {
|
||||
|
@ -20,5 +20,5 @@ class AriyalaHelper(ariyala: ActorRef) {
|
||||
|
||||
def downloadBiS(link: String, job: Job.Job)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[BiS] =
|
||||
(ariyala ? Ariyala.GetBiS(link, job)).mapTo[Seq[Piece]].map(BiS(_))
|
||||
(ariyala ? Ariyala.GetBiS(link, job)).mapTo[BiS]
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ class PlayerHelper(storage: ActorRef, ariyala: ActorRef) extends AriyalaHelper(a
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Seq[Player]] =
|
||||
maybePlayerId match {
|
||||
case Some(playerId) =>
|
||||
(storage ? DatabasePartyHandler.GetPlayer(playerId)).mapTo[Player].map(Seq(_))
|
||||
(storage ? DatabasePartyHandler.GetPlayer(playerId)).mapTo[Option[Player]].map(_.toSeq)
|
||||
case None =>
|
||||
(storage ? DatabasePartyHandler.GetParty(partyId)).mapTo[Party].map(_.players.values.toSeq)
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ class UserHelper(storage: ActorRef) {
|
||||
|
||||
def addUser(user: User, isHashedPassword: Boolean)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] =
|
||||
(storage ? DatabaseUserHandler.InsertUser(user, isHashedPassword)).mapTo[Int]
|
||||
(storage ? DatabaseUserHandler.AddUser(user, isHashedPassword)).mapTo[Int]
|
||||
|
||||
def user(partyId: String, username: String)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Option[User]] =
|
||||
|
@ -22,4 +22,5 @@ case class User(partyId: String,
|
||||
def hash: String = BCrypt.hashpw(password, BCrypt.gensalt)
|
||||
def verify(plain: String): Boolean = BCrypt.checkpw(plain, password)
|
||||
def verityScope(scope: Permission.Value): Boolean = permission >= scope
|
||||
def withHashedPassword: User = copy(password = hash)
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import akka.stream.ActorMaterializer
|
||||
import akka.stream.scaladsl.{Keep, Sink}
|
||||
import akka.util.ByteString
|
||||
import com.typesafe.scalalogging.StrictLogging
|
||||
import me.arcanis.ffxivbis.models.{Job, Piece}
|
||||
import me.arcanis.ffxivbis.models.{BiS, Job, Piece}
|
||||
import spray.json._
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
@ -39,7 +39,7 @@ class Ariyala extends Actor with StrictLogging {
|
||||
override def receive: Receive = {
|
||||
case GetBiS(link, job) =>
|
||||
val client = sender()
|
||||
get(link, job).pipeTo(client)
|
||||
get(link, job).map(BiS(_)).pipeTo(client)
|
||||
}
|
||||
|
||||
private def get(link: String, job: Job.Job): Future[Seq[Piece]] = {
|
||||
|
@ -19,6 +19,11 @@ trait Database extends Actor with StrictLogging {
|
||||
implicit def executionContext: ExecutionContext
|
||||
def profile: DatabaseProfile
|
||||
|
||||
override def postStop(): Unit = {
|
||||
profile.db.close()
|
||||
super.postStop()
|
||||
}
|
||||
|
||||
def filterParty(party: Party, maybePlayerId: Option[PlayerId]): Seq[Player] =
|
||||
(party, maybePlayerId) match {
|
||||
case (_, Some(playerId)) => party.player(playerId).map(Seq(_)).getOrElse(Seq.empty)
|
||||
|
@ -12,6 +12,8 @@ import akka.pattern.pipe
|
||||
import me.arcanis.ffxivbis.models.{BiS, Player, PlayerId}
|
||||
import me.arcanis.ffxivbis.service.Database
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
trait DatabasePartyHandler { this: Database =>
|
||||
import DatabasePartyHandler._
|
||||
|
||||
@ -26,11 +28,16 @@ trait DatabasePartyHandler { this: Database =>
|
||||
|
||||
case GetPlayer(playerId) =>
|
||||
val client = sender()
|
||||
val player = for {
|
||||
val player = profile.getPlayerFull(playerId).flatMap { maybePlayerData =>
|
||||
Future.traverse(maybePlayerData.toSeq) { playerData =>
|
||||
for {
|
||||
bis <- profile.getPiecesBiS(playerId)
|
||||
loot <- profile.getPieces(playerId)
|
||||
} yield Player(playerId.partyId, playerId.job, playerId.nick,
|
||||
BiS(bis.map(_.piece)), loot.map(_.piece))
|
||||
BiS(bis.map(_.piece)), loot.map(_.piece),
|
||||
playerData.link, playerData.priority)
|
||||
}
|
||||
}.map(_.headOption)
|
||||
player.pipeTo(client)
|
||||
|
||||
case RemovePlayer(playerId) =>
|
||||
|
@ -16,6 +16,11 @@ trait DatabaseUserHandler { this: Database =>
|
||||
import DatabaseUserHandler._
|
||||
|
||||
def userHandler: Receive = {
|
||||
case AddUser(user, isHashedPassword) =>
|
||||
val client = sender()
|
||||
val toInsert = if (isHashedPassword) user else user.withHashedPassword
|
||||
profile.insertUser(toInsert).pipeTo(client)
|
||||
|
||||
case DeleteUser(partyId, username) =>
|
||||
val client = sender()
|
||||
profile.deleteUser(partyId, username).pipeTo(client)
|
||||
@ -27,17 +32,12 @@ trait DatabaseUserHandler { this: Database =>
|
||||
case GetUsers(partyId) =>
|
||||
val client = sender()
|
||||
profile.getUsers(partyId).pipeTo(client)
|
||||
|
||||
case InsertUser(user, isHashedPassword) =>
|
||||
val client = sender()
|
||||
val toInsert = if (isHashedPassword) user else user.copy(password = user.hash)
|
||||
profile.insertUser(toInsert).pipeTo(client)
|
||||
}
|
||||
}
|
||||
|
||||
object DatabaseUserHandler {
|
||||
case class AddUser(user: User, isHashedPassword: Boolean)
|
||||
case class DeleteUser(partyId: String, username: String)
|
||||
case class GetUser(partyId: String, username: String)
|
||||
case class GetUsers(partyId: String)
|
||||
case class InsertUser(user: User, isHashedPassword: Boolean)
|
||||
}
|
||||
|
@ -44,7 +44,10 @@ trait LootProfile { this: DatabaseProfile =>
|
||||
}
|
||||
|
||||
def deletePieceById(piece: Piece)(playerId: Long): Future[Int] =
|
||||
db.run(pieceLoot(LootRep.fromPiece(playerId, piece)).take(1).delete)
|
||||
db.run(pieceLoot(LootRep.fromPiece(playerId, piece)).map(_.lootId).max.result).flatMap {
|
||||
case Some(id) => db.run(lootTable.filter(_.lootId === id).delete)
|
||||
case _ => throw new IllegalArgumentException(s"Could not find piece $piece belong to $playerId")
|
||||
}
|
||||
def getPiecesById(playerId: Long): Future[Seq[Loot]] = getPiecesById(Seq(playerId))
|
||||
def getPiecesById(playerIds: Seq[Long]): Future[Seq[Loot]] =
|
||||
db.run(piecesLoot(playerIds).result).map(_.map(_.toLoot))
|
||||
|
@ -10,6 +10,7 @@ package me.arcanis.ffxivbis.storage
|
||||
|
||||
import com.typesafe.config.Config
|
||||
import org.flywaydb.core.Flyway
|
||||
import org.flywaydb.core.api.configuration.ClassicConfiguration
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
@ -21,7 +22,16 @@ class Migration(config: Config) {
|
||||
val username = section.getString("db.user")
|
||||
val password = section.getString("db.password")
|
||||
|
||||
val flyway = Flyway.configure().dataSource(url, username, password).load()
|
||||
val provider = url match {
|
||||
case s"jdbc:$p:$_" => p
|
||||
case other => throw new NotImplementedError(s"unknown could not parse jdbc url from $other")
|
||||
}
|
||||
|
||||
val flywayConfiguration = new ClassicConfiguration
|
||||
flywayConfiguration.setLocationsAsStrings(s"db/migration/$provider")
|
||||
flywayConfiguration.setDataSource(url, username, password)
|
||||
val flyway = new Flyway(flywayConfiguration)
|
||||
|
||||
Future.successful(flyway.migrate())
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,8 @@ trait PlayersProfile { this: DatabaseProfile =>
|
||||
})
|
||||
def getPlayer(playerId: PlayerId): Future[Option[Long]] =
|
||||
db.run(player(playerId).map(_.playerId).result.headOption)
|
||||
def getPlayerFull(playerId: PlayerId): Future[Option[Player]] =
|
||||
db.run(player(playerId).result.headOption.map(_.map(_.toPlayer)))
|
||||
def getPlayers(partyId: String): Future[Seq[Long]] =
|
||||
db.run(players(partyId).map(_.playerId).result)
|
||||
def insertPlayer(playerObj: Player): Future[Int] =
|
||||
|
@ -22,7 +22,7 @@ trait UsersProfile { this: DatabaseProfile =>
|
||||
}
|
||||
object UserRep {
|
||||
def fromUser(user: User, id: Option[Long]): UserRep =
|
||||
UserRep(user.partyId, None, user.username, user.password, user.permission.toString)
|
||||
UserRep(user.partyId, id, user.username, user.password, user.permission.toString)
|
||||
}
|
||||
|
||||
class Users(tag: Tag) extends Table[UserRep](tag, "users") {
|
||||
@ -47,8 +47,8 @@ trait UsersProfile { this: DatabaseProfile =>
|
||||
def getUsers(partyId: String): Future[Seq[User]] =
|
||||
db.run(user(partyId, None).result).map(_.map(_.toUser))
|
||||
def insertUser(userObj: User): Future[Int] =
|
||||
db.run(user(userObj.partyId, Some(userObj.username)).result.headOption).map {
|
||||
case Some(user) => db.run(usersTable.update(UserRep.fromUser(userObj, user.userId)))
|
||||
db.run(user(userObj.partyId, Some(userObj.username)).map(_.userId).result.headOption).map {
|
||||
case Some(id) => db.run(usersTable.insertOrUpdate(UserRep.fromUser(userObj, Some(id))))
|
||||
case _ => db.run(usersTable.insertOrUpdate(UserRep.fromUser(userObj, None)))
|
||||
}.flatten
|
||||
|
||||
|
43
src/test/scala/me/arcanis/ffxivbis/models/Fixtures.scala
Normal file
43
src/test/scala/me/arcanis/ffxivbis/models/Fixtures.scala
Normal file
@ -0,0 +1,43 @@
|
||||
package me.arcanis.ffxivbis.models
|
||||
|
||||
import me.arcanis.ffxivbis.service.Party
|
||||
|
||||
object Fixtures {
|
||||
lazy val bis: BiS = BiS(
|
||||
Seq(
|
||||
Weapon(isTome = false ,Job.DNC),
|
||||
Head(isTome = false, Job.DNC),
|
||||
Body(isTome = false, Job.DNC),
|
||||
Hands(isTome = true, Job.DNC),
|
||||
Waist(isTome = true, Job.DNC),
|
||||
Legs(isTome = true, Job.DNC),
|
||||
Feet(isTome = false, Job.DNC),
|
||||
Ears(isTome = false, Job.DNC),
|
||||
Neck(isTome = true, Job.DNC),
|
||||
Wrist(isTome = false, Job.DNC),
|
||||
Ring(isTome = true, Job.DNC, "leftRing"),
|
||||
Ring(isTome = true, Job.DNC, "rightRing")
|
||||
)
|
||||
)
|
||||
|
||||
lazy val link: String = "https://ffxiv.ariyala.com/19V5R"
|
||||
|
||||
lazy val lootBody: Piece = Body(isTome = false, Job.DNC)
|
||||
lazy val lootHands: Piece = Hands(isTome = true, Job.DNC)
|
||||
lazy val lootLegs: Piece = Legs(isTome = false, Job.DNC)
|
||||
lazy val lootUpgrade: Piece = BodyUpgrade
|
||||
lazy val loot: Seq[Piece] = Seq(lootBody, lootHands, lootLegs, lootUpgrade)
|
||||
|
||||
lazy val partyId: String = Party.randomPartyId
|
||||
lazy val partyId2: String = Party.randomPartyId
|
||||
|
||||
lazy val playerEmpty: Player =
|
||||
Player(partyId, Job.DNC, "Siuan Sanche", BiS(), Seq.empty, Some(link))
|
||||
lazy val playerWithBiS: Player = playerEmpty.copy(bis = bis)
|
||||
|
||||
lazy val userPassword: String = "password"
|
||||
lazy val userPassword2: String = "pa55w0rd"
|
||||
lazy val userAdmin: User = User(partyId, "admin", userPassword, Permission.admin).withHashedPassword
|
||||
lazy val userGet: User = User(partyId, "get", userPassword, Permission.get).withHashedPassword
|
||||
lazy val users: Seq[User] = Seq(userAdmin, userGet)
|
||||
}
|
29
src/test/scala/me/arcanis/ffxivbis/models/Settings.scala
Normal file
29
src/test/scala/me/arcanis/ffxivbis/models/Settings.scala
Normal file
@ -0,0 +1,29 @@
|
||||
package me.arcanis.ffxivbis.models
|
||||
|
||||
import java.io.File
|
||||
|
||||
import com.typesafe.config.{Config, ConfigFactory, ConfigValueFactory}
|
||||
|
||||
object Settings {
|
||||
def config(values: Map[String, AnyRef]): Config = {
|
||||
@scala.annotation.tailrec
|
||||
def replace(acc: Config, iter: List[(String, AnyRef)]): Config = iter match {
|
||||
case Nil => acc
|
||||
case (key -> value) :: tail => replace(acc.withValue(key, ConfigValueFactory.fromAnyRef(value)), tail)
|
||||
}
|
||||
|
||||
val default = ConfigFactory.load()
|
||||
replace(default, values.toList)
|
||||
}
|
||||
|
||||
def clearDatabase(config: Config): Unit = {
|
||||
val databasePath =
|
||||
config.getString("me.arcanis.ffxivbis.database.sqlite.db.url").split(":").last
|
||||
val databaseFile = new File(databasePath)
|
||||
if (databaseFile.exists)
|
||||
databaseFile.delete()
|
||||
}
|
||||
def randomDatabasePath: String = File.createTempFile("ffxivdb-",".db").toPath.toString
|
||||
def withRandomDatabase: Config =
|
||||
config(Map("me.arcanis.ffxivbis.database.sqlite.db.url" -> s"jdbc:sqlite:$randomDatabasePath"))
|
||||
}
|
27
src/test/scala/me/arcanis/ffxivbis/service/AriyalaTest.scala
Normal file
27
src/test/scala/me/arcanis/ffxivbis/service/AriyalaTest.scala
Normal file
@ -0,0 +1,27 @@
|
||||
package me.arcanis.ffxivbis.service
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.testkit.{ImplicitSender, TestKit}
|
||||
import me.arcanis.ffxivbis.models.{Fixtures, Job}
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
|
||||
class AriyalaTest extends TestKit(ActorSystem("ariyala"))
|
||||
with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
|
||||
override def afterAll: Unit = TestKit.shutdownActorSystem(system)
|
||||
|
||||
"ariyala actor" must {
|
||||
|
||||
"get best in slot set" in {
|
||||
val ariyala = system.actorOf(Ariyala.props)
|
||||
ariyala ! Ariyala.GetBiS(Fixtures.link, Job.DNC)
|
||||
expectMsg(timeout, Fixtures.bis)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package me.arcanis.ffxivbis.service
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.pattern.ask
|
||||
import akka.testkit.{ImplicitSender, TestKit}
|
||||
import me.arcanis.ffxivbis.models.{Fixtures, Hands, Job, Piece, Player, Settings}
|
||||
import me.arcanis.ffxivbis.storage.Migration
|
||||
import me.arcanis.ffxivbis.utils.Compare
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
|
||||
class DatabaseBiSHandlerTest
|
||||
extends TestKit(ActorSystem("database-bis-handler", Settings.withRandomDatabase))
|
||||
with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
|
||||
private val database = system.actorOf(impl.DatabaseImpl.props)
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
|
||||
override def beforeAll: Unit = {
|
||||
Await.result(Migration(system.settings.config), timeout)
|
||||
Await.result((database ? impl.DatabasePartyHandler.AddPlayer(Fixtures.playerEmpty))(timeout).mapTo[Int], timeout)
|
||||
}
|
||||
|
||||
override def afterAll: Unit = {
|
||||
TestKit.shutdownActorSystem(system)
|
||||
Settings.clearDatabase(system.settings.config)
|
||||
}
|
||||
|
||||
"database bis handler" must {
|
||||
|
||||
"add pieces to bis" in {
|
||||
database ! impl.DatabaseBiSHandler.AddPieceToBis(Fixtures.playerEmpty.playerId, Fixtures.lootBody)
|
||||
expectMsg(timeout, 1)
|
||||
|
||||
database ! impl.DatabaseBiSHandler.AddPieceToBis(Fixtures.playerEmpty.playerId, Fixtures.lootHands)
|
||||
expectMsg(timeout, 1)
|
||||
}
|
||||
|
||||
"get party bis set" in {
|
||||
database ! impl.DatabaseBiSHandler.GetBiS(Fixtures.playerEmpty.partyId, None)
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyBiSCompare(party, Seq(Fixtures.lootBody, Fixtures.lootHands)) => ()
|
||||
}
|
||||
}
|
||||
|
||||
"get bis set" in {
|
||||
database ! impl.DatabaseBiSHandler.GetBiS(Fixtures.playerEmpty.partyId, Some(Fixtures.playerEmpty.playerId))
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyBiSCompare(party, Seq(Fixtures.lootBody, Fixtures.lootHands)) => ()
|
||||
}
|
||||
}
|
||||
|
||||
"remove piece from bis set" in {
|
||||
database ! impl.DatabaseBiSHandler.RemovePieceFromBiS(Fixtures.playerEmpty.playerId, Fixtures.lootBody)
|
||||
expectMsg(timeout, 1)
|
||||
|
||||
database ! impl.DatabaseBiSHandler.GetBiS(Fixtures.playerEmpty.partyId, None)
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyBiSCompare(party, Seq(Fixtures.lootHands)) => ()
|
||||
}
|
||||
}
|
||||
|
||||
"update piece in bis set" in {
|
||||
val newPiece = Hands(isTome = false, Job.DNC)
|
||||
|
||||
database ! impl.DatabaseBiSHandler.AddPieceToBis(Fixtures.playerEmpty.playerId, newPiece)
|
||||
expectMsg(timeout, 1)
|
||||
|
||||
database ! impl.DatabaseBiSHandler.GetBiS(Fixtures.playerEmpty.partyId, None)
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyBiSCompare(party, Seq(newPiece)) => ()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private def partyBiSCompare[T](party: Seq[T], bis: Seq[Piece]): Boolean =
|
||||
Compare.seqEquals(party.foldLeft(Seq.empty[Piece]){ case (acc, player) => acc ++ player.asInstanceOf[Player].bis.pieces }, bis)
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package me.arcanis.ffxivbis.service
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.pattern.ask
|
||||
import akka.testkit.{ImplicitSender, TestKit}
|
||||
import me.arcanis.ffxivbis.models.{Fixtures, Piece, Player, Settings}
|
||||
import me.arcanis.ffxivbis.storage.Migration
|
||||
import me.arcanis.ffxivbis.utils.Compare
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
|
||||
class DatabaseLootHandlerTest
|
||||
extends TestKit(ActorSystem("database-loot-handler", Settings.withRandomDatabase))
|
||||
with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
|
||||
private val database = system.actorOf(impl.DatabaseImpl.props)
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
|
||||
override def beforeAll: Unit = {
|
||||
Await.result(Migration(system.settings.config), timeout)
|
||||
Await.result((database ? impl.DatabasePartyHandler.AddPlayer(Fixtures.playerEmpty))(timeout).mapTo[Int], timeout)
|
||||
}
|
||||
|
||||
override def afterAll: Unit = {
|
||||
TestKit.shutdownActorSystem(system)
|
||||
Settings.clearDatabase(system.settings.config)
|
||||
}
|
||||
|
||||
"database loot handler actor" must {
|
||||
|
||||
"add loot" in {
|
||||
Fixtures.loot.foreach { piece =>
|
||||
database ! impl.DatabaseLootHandler.AddPieceTo(Fixtures.playerEmpty.playerId, piece)
|
||||
expectMsg(timeout, 1)
|
||||
}
|
||||
}
|
||||
|
||||
"get party loot" in {
|
||||
database ! impl.DatabaseLootHandler.GetLoot(Fixtures.playerEmpty.partyId, None)
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyLootCompare(party, Fixtures.loot) => ()
|
||||
}
|
||||
}
|
||||
|
||||
"get loot" in {
|
||||
database ! impl.DatabaseLootHandler.GetLoot(Fixtures.playerEmpty.partyId, Some(Fixtures.playerEmpty.playerId))
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyLootCompare(party, Fixtures.loot) => ()
|
||||
}
|
||||
}
|
||||
|
||||
"remove loot" in {
|
||||
database ! impl.DatabaseLootHandler.RemovePieceFrom(Fixtures.playerEmpty.playerId, Fixtures.lootBody)
|
||||
expectMsg(timeout, 1)
|
||||
|
||||
val newLoot = Fixtures.loot.filterNot(_ == Fixtures.lootBody)
|
||||
|
||||
database ! impl.DatabaseLootHandler.GetLoot(Fixtures.playerEmpty.partyId, None)
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyLootCompare(party, newLoot) => ()
|
||||
}
|
||||
}
|
||||
|
||||
"add same loot" in {
|
||||
database ! impl.DatabaseLootHandler.AddPieceTo(Fixtures.playerEmpty.playerId, Fixtures.lootBody)
|
||||
expectMsg(timeout, 1)
|
||||
|
||||
Fixtures.loot.foreach { piece =>
|
||||
database ! impl.DatabaseLootHandler.AddPieceTo(Fixtures.playerEmpty.playerId, piece)
|
||||
expectMsg(timeout, 1)
|
||||
}
|
||||
|
||||
database ! impl.DatabaseLootHandler.GetLoot(Fixtures.playerEmpty.partyId, None)
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyLootCompare(party, Fixtures.loot ++ Fixtures.loot) => ()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private def partyLootCompare[T](party: Seq[T], loot: Seq[Piece]): Boolean =
|
||||
Compare.seqEquals(party.foldLeft(Seq.empty[Piece]){ case (acc, player) => acc ++ player.asInstanceOf[Player].loot }, loot)
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package me.arcanis.ffxivbis.service
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.testkit.{ImplicitSender, TestKit}
|
||||
import me.arcanis.ffxivbis.models.{Fixtures, Settings}
|
||||
import me.arcanis.ffxivbis.storage.Migration
|
||||
import me.arcanis.ffxivbis.utils.Compare
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
|
||||
class DatabasePartyHandlerTest
|
||||
extends TestKit(ActorSystem("database-party-handler", Settings.withRandomDatabase))
|
||||
with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
|
||||
private val database = system.actorOf(impl.DatabaseImpl.props)
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
|
||||
override def beforeAll: Unit = {
|
||||
Await.result(Migration(system.settings.config), timeout)
|
||||
}
|
||||
|
||||
override def afterAll: Unit = {
|
||||
TestKit.shutdownActorSystem(system)
|
||||
Settings.clearDatabase(system.settings.config)
|
||||
}
|
||||
|
||||
"database party handler actor" must {
|
||||
|
||||
"add player" in {
|
||||
database ! impl.DatabasePartyHandler.AddPlayer(Fixtures.playerEmpty)
|
||||
expectMsg(timeout, 1)
|
||||
}
|
||||
|
||||
"get party" in {
|
||||
database ! impl.DatabasePartyHandler.GetParty(Fixtures.partyId)
|
||||
expectMsgPF(timeout) {
|
||||
case p: Party if Compare.seqEquals(p.getPlayers, Seq(Fixtures.playerEmpty)) => ()
|
||||
}
|
||||
}
|
||||
|
||||
"get player" in {
|
||||
database ! impl.DatabasePartyHandler.GetPlayer(Fixtures.playerEmpty.playerId)
|
||||
expectMsg(timeout, Some(Fixtures.playerEmpty))
|
||||
}
|
||||
|
||||
"update player" in {
|
||||
val newPlayer = Fixtures.playerEmpty.copy(priority = 2)
|
||||
|
||||
database ! impl.DatabasePartyHandler.AddPlayer(newPlayer)
|
||||
expectMsg(timeout, 1)
|
||||
|
||||
database ! impl.DatabasePartyHandler.GetPlayer(newPlayer.playerId)
|
||||
expectMsg(timeout, Some(newPlayer))
|
||||
|
||||
database ! impl.DatabasePartyHandler.GetParty(Fixtures.partyId)
|
||||
expectMsgPF(timeout) {
|
||||
case p: Party if Compare.seqEquals(p.getPlayers, Seq(newPlayer)) => ()
|
||||
}
|
||||
}
|
||||
|
||||
"remove player" in {
|
||||
database ! impl.DatabasePartyHandler.RemovePlayer(Fixtures.playerEmpty.playerId)
|
||||
expectMsg(timeout, 1)
|
||||
|
||||
database ! impl.DatabasePartyHandler.GetPlayer(Fixtures.playerEmpty.playerId)
|
||||
expectMsg(timeout, None)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package me.arcanis.ffxivbis.service
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.testkit.{ImplicitSender, TestKit}
|
||||
import me.arcanis.ffxivbis.models.{Fixtures, Settings}
|
||||
import me.arcanis.ffxivbis.storage.Migration
|
||||
import me.arcanis.ffxivbis.utils.Compare
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
|
||||
class DatabaseUserHandlerTest
|
||||
extends TestKit(ActorSystem("database-user-handler", Settings.withRandomDatabase))
|
||||
with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
|
||||
private val database = system.actorOf(impl.DatabaseImpl.props)
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
|
||||
override def beforeAll: Unit = {
|
||||
Await.result(Migration(system.settings.config), timeout)
|
||||
}
|
||||
|
||||
override def afterAll: Unit = {
|
||||
TestKit.shutdownActorSystem(system)
|
||||
Settings.clearDatabase(system.settings.config)
|
||||
}
|
||||
|
||||
"database user handler actor" must {
|
||||
|
||||
"add user" in {
|
||||
database ! impl.DatabaseUserHandler.AddUser(Fixtures.userAdmin, isHashedPassword = true)
|
||||
expectMsg(timeout, 1)
|
||||
}
|
||||
|
||||
"get user" in {
|
||||
database ! impl.DatabaseUserHandler.GetUser(Fixtures.partyId, Fixtures.userAdmin.username)
|
||||
expectMsg(timeout, Some(Fixtures.userAdmin))
|
||||
}
|
||||
|
||||
"get users" in {
|
||||
database ! impl.DatabaseUserHandler.AddUser(Fixtures.userGet, isHashedPassword = true)
|
||||
expectMsg(timeout, 1)
|
||||
|
||||
database ! impl.DatabaseUserHandler.GetUsers(Fixtures.partyId)
|
||||
expectMsgPF(timeout) {
|
||||
case u: Seq[_] if Compare.seqEquals(u, Fixtures.users) => ()
|
||||
}
|
||||
}
|
||||
|
||||
"update user" in {
|
||||
val newUser= Fixtures.userGet.copy(password = Fixtures.userPassword2).withHashedPassword
|
||||
val newUserSet = Seq(newUser, Fixtures.userAdmin)
|
||||
|
||||
database ! impl.DatabaseUserHandler.AddUser(newUser, isHashedPassword = true)
|
||||
expectMsg(timeout, 1)
|
||||
|
||||
database ! impl.DatabaseUserHandler.GetUser(Fixtures.partyId, newUser.username)
|
||||
expectMsg(timeout, Some(newUser))
|
||||
|
||||
database ! impl.DatabaseUserHandler.GetUsers(Fixtures.partyId)
|
||||
expectMsgPF(timeout) {
|
||||
case u: Seq[_] if Compare.seqEquals(u, newUserSet) => ()
|
||||
}
|
||||
}
|
||||
|
||||
"remove user" in {
|
||||
database ! impl.DatabaseUserHandler.DeleteUser(Fixtures.partyId, Fixtures.userGet.username)
|
||||
expectMsg(timeout, 1)
|
||||
|
||||
database ! impl.DatabaseUserHandler.GetUser(Fixtures.partyId, Fixtures.userGet.username)
|
||||
expectMsg(timeout, None)
|
||||
}
|
||||
}
|
||||
}
|
8
src/test/scala/me/arcanis/ffxivbis/utils/Compare.scala
Normal file
8
src/test/scala/me/arcanis/ffxivbis/utils/Compare.scala
Normal file
@ -0,0 +1,8 @@
|
||||
package me.arcanis.ffxivbis.utils
|
||||
|
||||
object Compare {
|
||||
def seqEquals[T](left: Seq[T], right: Seq[T]): Boolean =
|
||||
left.groupBy(identity).view.mapValues(_.size).forall {
|
||||
case (key, count) => right.count(_ == key) == count
|
||||
}
|
||||
}
|
4
test.sbt
Normal file
4
test.sbt
Normal file
@ -0,0 +1,4 @@
|
||||
libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.8"
|
||||
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % "test"
|
||||
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-testkit" % "2.5.26" % "test"
|
1
version.sbt
Normal file
1
version.sbt
Normal file
@ -0,0 +1 @@
|
||||
version := "0.9.0"
|
Loading…
Reference in New Issue
Block a user