You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
7.0 KiB
216 lines
7.0 KiB
package com.xsn.explorer.data
|
|
|
|
import com.alexitc.playsonify.models.ordering.{FieldOrdering, OrderingCondition}
|
|
import com.alexitc.playsonify.models.pagination.{Limit, Offset, PaginatedQuery}
|
|
import com.alexitc.playsonify.sql.FieldOrderingSQLInterpreter
|
|
import com.xsn.explorer.data.anorm.BalancePostgresDataHandler
|
|
import com.xsn.explorer.data.anorm.dao.BalancePostgresDAO
|
|
import com.xsn.explorer.data.common.PostgresDataHandlerSpec
|
|
import com.xsn.explorer.helpers.DataHelper
|
|
import com.xsn.explorer.models.fields.BalanceField
|
|
import com.xsn.explorer.models.persisted.Balance
|
|
import org.scalactic.Good
|
|
|
|
class BalancePostgresDataHandlerSpec extends PostgresDataHandlerSpec {
|
|
|
|
import DataHelper._
|
|
|
|
lazy val dataHandler = new BalancePostgresDataHandler(database, new BalancePostgresDAO(new FieldOrderingSQLInterpreter))
|
|
|
|
val defaultOrdering = FieldOrdering(BalanceField.Available, OrderingCondition.DescendingOrder)
|
|
|
|
"upsert" should {
|
|
"create an empty balance" in {
|
|
val address = DataHelper.createAddress("XxQ7j37LfuXgsLd5DZAwFKhT3s2ZMkW85F")
|
|
val balance = Balance(address)
|
|
|
|
val result = dataHandler.upsert(balance)
|
|
result mustEqual Good(balance)
|
|
}
|
|
|
|
"update an existing balance" in {
|
|
val address = DataHelper.createAddress("XfAATXtkRgCdMTrj2fxHvLsKLLmqAjhEAt")
|
|
val initialBalance = Balance(address, received = BigDecimal(10), spent = BigDecimal(5))
|
|
val patch = Balance(address, received = BigDecimal(10), spent = BigDecimal(10))
|
|
val expected = combine(initialBalance, patch)
|
|
|
|
dataHandler.upsert(initialBalance)
|
|
|
|
val result = dataHandler.upsert(patch)
|
|
result mustEqual Good(expected)
|
|
}
|
|
}
|
|
|
|
"get" should {
|
|
|
|
val balances = List(
|
|
Balance(
|
|
address = DataHelper.createAddress("XxQ7j37LfuXgsLd5DZAwFKhT3s2ZMkW85F"),
|
|
received = BigDecimal("1000"),
|
|
spent = BigDecimal("0")),
|
|
|
|
Balance(
|
|
address = DataHelper.createAddress("Xbh5pJdBNm8J9PxnEmwVcuQKRmZZ7DkpcF"),
|
|
received = BigDecimal("1000"),
|
|
spent = BigDecimal("100")),
|
|
|
|
Balance(
|
|
address = DataHelper.createAddress("XfAATXtkRgCdMTrj2fxHvLsKLLmqAjhEAt"),
|
|
received = BigDecimal("10000"),
|
|
spent = BigDecimal("1000")),
|
|
|
|
Balance(
|
|
address = DataHelper.createAddress("XiHW7SR56UPHeXKwcpeVsE4nUfkHv5RqE3"),
|
|
received = BigDecimal("1000"),
|
|
spent = BigDecimal("500"))
|
|
).sortBy(_.available).reverse
|
|
|
|
def prepare() = {
|
|
clearDatabase()
|
|
|
|
balances
|
|
.map(dataHandler.upsert)
|
|
.foreach(_.isGood mustEqual true)
|
|
}
|
|
|
|
"return the first 3 richest addresses" in {
|
|
prepare()
|
|
val query = PaginatedQuery(Offset(0), Limit(3))
|
|
val expected = balances.take(3)
|
|
|
|
val result = dataHandler.get(query, defaultOrdering)
|
|
result.map(_.data) mustEqual Good(expected)
|
|
}
|
|
|
|
"skip the first richest address" in {
|
|
prepare()
|
|
val query = PaginatedQuery(Offset(1), Limit(3))
|
|
val expected = balances.drop(1).take(3)
|
|
|
|
val result = dataHandler.get(query, defaultOrdering)
|
|
result.map(_.data) mustEqual Good(expected)
|
|
}
|
|
}
|
|
|
|
"getBy address" should {
|
|
"return empty values for unknown address" in {
|
|
val address = DataHelper.createAddress("XxQ7j37LfuXGSld5DZAwFKhT3s2ZMkW85F")
|
|
val expected = Balance(address)
|
|
|
|
val result = dataHandler.getBy(address)
|
|
result mustEqual Good(expected)
|
|
}
|
|
|
|
"return the balance" in {
|
|
val address = DataHelper.createAddress("XxQ7j37LfuXgsLd5DZAWfKhT3s2ZMkW85F")
|
|
val balance = Balance(address, 1000, 500)
|
|
|
|
dataHandler.upsert(balance).isGood mustEqual true
|
|
val result = dataHandler.getBy(address)
|
|
result mustEqual Good(balance)
|
|
}
|
|
}
|
|
|
|
"getNonZeroBalances" should {
|
|
val balances = List(
|
|
Balance(
|
|
address = DataHelper.createAddress("XiHW7SR56uPHeXKwcpeVsE4nUfkHv5RqE3"),
|
|
received = BigDecimal("0"),
|
|
spent = BigDecimal("0"))
|
|
).sortBy(_.available).reverse
|
|
|
|
def prepare() = {
|
|
clearDatabase()
|
|
|
|
balances
|
|
.map(dataHandler.upsert)
|
|
.foreach(_.isGood mustEqual true)
|
|
}
|
|
|
|
"ignore addresses with balance = 0" in {
|
|
prepare()
|
|
val query = PaginatedQuery(Offset(0), Limit(1))
|
|
val expected = List.empty[Balance]
|
|
|
|
val result = dataHandler.getNonZeroBalances(query, defaultOrdering)
|
|
result.map(_.data) mustEqual Good(expected)
|
|
result.get.total.int mustEqual balances.size - 1
|
|
}
|
|
}
|
|
|
|
"getHighestBalances" should {
|
|
|
|
val balances = List(
|
|
Balance(createAddress("XiHW7SR56uPHeXKwcpeVsE4nUfkHv5RqE3"), received = 1000),
|
|
Balance(createAddress("XjHW7SR56uPHeXKwcpeVsE4nUfkHv5RqE3"), received = 900),
|
|
Balance(createAddress("XkHW7SR56uPHeXKwcpeVsE4nUfkHv5RqE3"), received = 900, spent = 100),
|
|
Balance(createAddress("XlHW7SR56uPHeXKwcpeVsE4nUfkHv5RqE3"), received = 800),
|
|
Balance(createAddress("XmmmmSR56uPHeXKwcpeVsE4nUfkHv5RqE3"), received = 700),
|
|
Balance(createAddress("XnHW7SR56uPHeXKwcpeVsE4nUfkHv5RqE3"), received = 600),
|
|
Balance(createAddress("XxxxxSR56uPHeXKwcpeVsE4nUfkHv5RqE3"), received = 2000),
|
|
)
|
|
|
|
def prepare() = {
|
|
clearDatabase()
|
|
|
|
balances.foreach(dataHandler.upsert(_).isGood mustEqual true)
|
|
database.withConnection { implicit conn =>
|
|
_root_.anorm
|
|
.SQL(
|
|
s"""
|
|
|INSERT INTO hidden_addresses (address) VALUES
|
|
| ('${balances(4).address.string}'),
|
|
| ('${balances(6).address.string}')
|
|
|""".stripMargin)
|
|
.executeUpdate()
|
|
}
|
|
}
|
|
|
|
"return the highest balances" in {
|
|
prepare()
|
|
|
|
val expected = balances.head
|
|
val result = dataHandler.getHighestBalances(Limit(1), None).get
|
|
result mustEqual List(expected)
|
|
}
|
|
|
|
"return the next elements given the last seen address" in {
|
|
prepare()
|
|
|
|
val lastSeenAddress = balances.head.address
|
|
val expected = balances(1)
|
|
val result = dataHandler.getHighestBalances(Limit(1), Option(lastSeenAddress)).get
|
|
result mustEqual List(expected)
|
|
}
|
|
|
|
"return the element with the same time breaking ties by address" in {
|
|
prepare()
|
|
|
|
val lastSeenAddress = balances(2).address
|
|
val expected = balances(3)
|
|
val result = dataHandler.getHighestBalances(Limit(1), Option(lastSeenAddress)).get
|
|
result mustEqual List(expected)
|
|
}
|
|
|
|
"return the no elements on unknown lastSeenTransaction" in {
|
|
val lastSeenAddress = createAddress("XmHW7SR56uPHeXKwcpeVsE4nUfkHv5Rq12")
|
|
val result = dataHandler.getHighestBalances(Limit(1), Option(lastSeenAddress)).get
|
|
result must be(empty)
|
|
}
|
|
|
|
"exclude hidden_addresses" in {
|
|
prepare()
|
|
|
|
val lastSeenAddress = balances(3).address
|
|
val expected = balances(5)
|
|
val result = dataHandler.getHighestBalances(Limit(1), Option(lastSeenAddress)).get
|
|
result mustEqual List(expected)
|
|
}
|
|
}
|
|
|
|
private def combine(balances: Balance*): Balance = {
|
|
balances.reduce { (a, b) =>
|
|
Balance(a.address, a.received + b.received, a.spent + b.spent)
|
|
}
|
|
}
|
|
}
|
|
|