summaryrefslogtreecommitdiff
path: root/game-engine/src/test/kotlin
diff options
context:
space:
mode:
Diffstat (limited to 'game-engine/src/test/kotlin')
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/moves/BuildWonderMoveTest.kt76
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/BestPriceCalculatorTest.kt129
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ProductionTest.kt323
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactionsTest.kt36
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourcesTest.kt482
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/TradingRulesTest.kt127
6 files changed, 1173 insertions, 0 deletions
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/moves/BuildWonderMoveTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/moves/BuildWonderMoveTest.kt
new file mode 100644
index 00000000..ee461e38
--- /dev/null
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/moves/BuildWonderMoveTest.kt
@@ -0,0 +1,76 @@
+package org.luxons.sevenwonders.game.moves
+
+import org.junit.Assert.assertEquals
+import org.junit.Assert.fail
+import org.junit.Test
+import org.luxons.sevenwonders.game.Settings
+import org.luxons.sevenwonders.game.api.Table
+import org.luxons.sevenwonders.game.cards.Card
+import org.luxons.sevenwonders.game.test.createMove
+import org.luxons.sevenwonders.game.test.sampleCards
+import org.luxons.sevenwonders.game.test.testCard
+import org.luxons.sevenwonders.game.test.testSettings
+import org.luxons.sevenwonders.game.test.testTable
+
+class BuildWonderMoveTest {
+
+ @Test(expected = InvalidMoveException::class)
+ fun validate_failsWhenCardNotInHand() {
+ val table = testTable(3)
+ val hand = sampleCards(0, 7)
+ val anotherCard = testCard("Card that is not in the hand")
+ val move = createMove(0, anotherCard, MoveType.UPGRADE_WONDER)
+
+ move.validate(table, hand)
+ }
+
+ @Test(expected = InvalidMoveException::class)
+ fun validate_failsWhenWonderIsCompletelyBuilt() {
+ val settings = testSettings(3)
+ val table = testTable(settings)
+ val hand = sampleCards(0, 7)
+
+ fillPlayerWonderLevels(settings, table, hand)
+
+ // should fail because the wonder is already full
+ buildOneWonderLevel(settings, table, hand, 4)
+ }
+
+ private fun fillPlayerWonderLevels(settings: Settings, table: Table, hand: List<Card>) {
+ try {
+ val nbLevels = table.getBoard(0).wonder.stages.size
+ for (i in 0 until nbLevels) {
+ buildOneWonderLevel(settings, table, hand, i)
+ }
+ } catch (e: InvalidMoveException) {
+ fail("Building wonder levels should not fail before being full")
+ }
+ }
+
+ private fun buildOneWonderLevel(settings: Settings, table: Table, hand: List<Card>, cardIndex: Int) {
+ val card = hand[cardIndex]
+ val move = createMove(0, card, MoveType.UPGRADE_WONDER)
+ move.validate(table, hand)
+ move.place(table, mutableListOf(), settings)
+ move.activate(table, emptyList(), settings)
+ }
+
+ @Test
+ fun place_increasesWonderLevel() {
+ val settings = testSettings(3)
+ val table = testTable(settings)
+ val hand = sampleCards(0, 7)
+ val cardToUse = hand[0]
+ val move = createMove(0, cardToUse, MoveType.UPGRADE_WONDER)
+ move.validate(table, hand) // should not fail
+
+ val initialStage = table.getBoard(0).wonder.nbBuiltStages
+
+ move.place(table, mutableListOf(), settings)
+
+ val newStage = table.getBoard(0).wonder.nbBuiltStages
+
+ // we need to see the level increase before activation so that other players
+ assertEquals((initialStage + 1).toLong(), newStage.toLong())
+ }
+}
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/BestPriceCalculatorTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/BestPriceCalculatorTest.kt
new file mode 100644
index 00000000..f4cf5294
--- /dev/null
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/BestPriceCalculatorTest.kt
@@ -0,0 +1,129 @@
+package org.luxons.sevenwonders.game.resources
+
+import java.util.Arrays
+
+import org.junit.Test
+import org.luxons.sevenwonders.game.api.Table
+import org.luxons.sevenwonders.game.boards.Board
+import org.luxons.sevenwonders.game.test.*
+
+import org.junit.Assert.assertEquals
+import org.luxons.sevenwonders.game.resources.Provider.LEFT_PLAYER
+import org.luxons.sevenwonders.game.resources.Provider.RIGHT_PLAYER
+import org.luxons.sevenwonders.game.resources.ResourceType.CLAY
+import org.luxons.sevenwonders.game.resources.ResourceType.GLASS
+import org.luxons.sevenwonders.game.resources.ResourceType.ORE
+import org.luxons.sevenwonders.game.resources.ResourceType.STONE
+import org.luxons.sevenwonders.game.resources.ResourceType.WOOD
+
+class BestPriceCalculatorTest {
+
+ @Test
+ fun bestPrice_0forEmptyResources() {
+ val table = testTable(3)
+ val resources = Resources()
+ assertEquals(0, BestPriceCalculator.bestPrice(resources, table, 0).toLong())
+ assertEquals(ResourceTransactions(), BestPriceCalculator.bestSolution(resources, table, 0))
+ }
+
+ @Test
+ fun bestPrice_fixedResources_defaultCost() {
+ val left = testBoard(STONE)
+ val main = testBoard(STONE)
+ val right = testBoard(WOOD)
+ val table = Table(Arrays.asList(main, right, left))
+
+ val resources = createResources(STONE, STONE)
+ assertEquals(2, BestPriceCalculator.bestPrice(resources, table, 0).toLong())
+ assertEquals(4, BestPriceCalculator.bestPrice(resources, table, 1).toLong())
+ assertEquals(2, BestPriceCalculator.bestPrice(resources, table, 2).toLong())
+
+ val stoneLeftSingle = createTransaction(LEFT_PLAYER, STONE)
+ val stoneRightSingle = createTransaction(RIGHT_PLAYER, STONE)
+
+ val stoneLeft = createTransactions(stoneLeftSingle)
+ val stoneRight = createTransactions(stoneRightSingle)
+ val stoneLeftAndRight = createTransactions(stoneLeftSingle, stoneRightSingle)
+
+ assertEquals(stoneLeft, BestPriceCalculator.bestSolution(resources, table, 0))
+ assertEquals(stoneLeftAndRight, BestPriceCalculator.bestSolution(resources, table, 1))
+ assertEquals(stoneRight, BestPriceCalculator.bestSolution(resources, table, 2))
+ }
+
+ @Test
+ fun bestPrice_fixedResources_overridenCost() {
+ val main = testBoard(STONE)
+ main.tradingRules.setCost(WOOD, RIGHT_PLAYER, 1)
+
+ val left = testBoard(WOOD)
+ val right = testBoard(WOOD)
+ val opposite = testBoard(GLASS)
+ val table = Table(Arrays.asList(main, right, opposite, left))
+
+ val resources = createResources(WOOD)
+ assertEquals(1, BestPriceCalculator.bestPrice(resources, table, 0).toLong())
+ assertEquals(0, BestPriceCalculator.bestPrice(resources, table, 1).toLong())
+ assertEquals(2, BestPriceCalculator.bestPrice(resources, table, 2).toLong())
+ assertEquals(0, BestPriceCalculator.bestPrice(resources, table, 3).toLong())
+
+ val woodLeft = createTransactions(LEFT_PLAYER, WOOD)
+ val woodRight = createTransactions(RIGHT_PLAYER, WOOD)
+ assertEquals(woodRight, BestPriceCalculator.bestSolution(resources, table, 0))
+ assertEquals(ResourceTransactions(), BestPriceCalculator.bestSolution(resources, table, 1))
+ assertEquals(woodLeft, BestPriceCalculator.bestSolution(resources, table, 2))
+ assertEquals(ResourceTransactions(), BestPriceCalculator.bestSolution(resources, table, 3))
+ }
+
+ @Test
+ fun bestPrice_mixedResources_overridenCost() {
+ val left = testBoard(WOOD)
+
+ val main = testBoard(STONE)
+ main.tradingRules.setCost(WOOD, RIGHT_PLAYER, 1)
+
+ val right = testBoard(ORE)
+ right.production.addChoice(WOOD, CLAY)
+ right.publicProduction.addChoice(WOOD, CLAY)
+
+ val table = Table(Arrays.asList(main, right, left))
+
+ val resources = createResources(WOOD)
+ assertEquals(1, BestPriceCalculator.bestPrice(resources, table, 0).toLong())
+ assertEquals(0, BestPriceCalculator.bestPrice(resources, table, 1).toLong())
+ assertEquals(0, BestPriceCalculator.bestPrice(resources, table, 2).toLong())
+
+ val woodRight = createTransactions(RIGHT_PLAYER, WOOD)
+
+ assertEquals(woodRight, BestPriceCalculator.bestSolution(resources, table, 0))
+ assertEquals(ResourceTransactions(), BestPriceCalculator.bestSolution(resources, table, 1))
+ assertEquals(ResourceTransactions(), BestPriceCalculator.bestSolution(resources, table, 2))
+ }
+
+ @Test
+ fun bestPrice_chooseCheapest() {
+ val left = testBoard(WOOD)
+
+ val main = testBoard(WOOD)
+ main.production.addChoice(CLAY, ORE)
+ main.tradingRules.setCost(CLAY, RIGHT_PLAYER, 1)
+
+ val right = testBoard(WOOD)
+ right.production.addFixedResource(ORE, 1)
+ right.production.addFixedResource(CLAY, 1)
+ right.publicProduction.addFixedResource(ORE, 1)
+ right.publicProduction.addFixedResource(CLAY, 1)
+
+ val table = Table(Arrays.asList(main, right, left))
+
+ val resources = createResources(ORE, CLAY)
+ assertEquals(1, BestPriceCalculator.bestPrice(resources, table, 0).toLong())
+ assertEquals(0, BestPriceCalculator.bestPrice(resources, table, 1).toLong())
+ assertEquals(4, BestPriceCalculator.bestPrice(resources, table, 2).toLong())
+
+ val oreAndClayLeft = createTransactions(LEFT_PLAYER, ORE, CLAY)
+ val clayRight = createTransactions(RIGHT_PLAYER, CLAY)
+ assertEquals(clayRight, BestPriceCalculator.bestSolution(resources, table, 0))
+ assertEquals(ResourceTransactions(), BestPriceCalculator.bestSolution(resources, table, 1))
+ assertEquals(oreAndClayLeft, BestPriceCalculator.bestSolution(resources, table, 2))
+ }
+}
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ProductionTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ProductionTest.kt
new file mode 100644
index 00000000..27f85c1a
--- /dev/null
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ProductionTest.kt
@@ -0,0 +1,323 @@
+package org.luxons.sevenwonders.game.resources
+
+import java.util.EnumSet
+import java.util.HashSet
+
+import org.junit.Before
+import org.junit.Test
+
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+
+class ProductionTest {
+
+ private var emptyResources: Resources? = null
+
+ private var resources1Wood: Resources? = null
+
+ private var resources1Stone: Resources? = null
+
+ private var resources1Stone1Wood: Resources? = null
+
+ private var resources2Stones: Resources? = null
+
+ private var resources2Stones3Clay: Resources? = null
+
+ @Before
+ fun init() {
+ emptyResources = Resources()
+
+ resources1Wood = Resources()
+ resources1Wood!!.add(ResourceType.WOOD, 1)
+
+ resources1Stone = Resources()
+ resources1Stone!!.add(ResourceType.STONE, 1)
+
+ resources1Stone1Wood = Resources()
+ resources1Stone1Wood!!.add(ResourceType.STONE, 1)
+ resources1Stone1Wood!!.add(ResourceType.WOOD, 1)
+
+ resources2Stones = Resources()
+ resources2Stones!!.add(ResourceType.STONE, 2)
+
+ resources2Stones3Clay = Resources()
+ resources2Stones3Clay!!.add(ResourceType.STONE, 2)
+ resources2Stones3Clay!!.add(ResourceType.CLAY, 3)
+ }
+
+ @Test
+ fun contains_newProductionContainsEmpty() {
+ val production = Production()
+ assertTrue(production.contains(emptyResources))
+ }
+
+ @Test
+ fun contains_singleFixedResource_noneAtAll() {
+ val production = Production()
+ assertFalse(production.contains(resources2Stones))
+ }
+
+ @Test
+ fun contains_singleFixedResource_notEnough() {
+ val production = Production()
+ production.addFixedResource(ResourceType.STONE, 1)
+ assertFalse(production.contains(resources2Stones))
+ }
+
+ @Test
+ fun contains_singleFixedResource_justEnough() {
+ val production = Production()
+ production.addFixedResource(ResourceType.STONE, 2)
+ assertTrue(production.contains(resources2Stones))
+ }
+
+ @Test
+ fun contains_singleFixedResource_moreThanEnough() {
+ val production = Production()
+ production.addFixedResource(ResourceType.STONE, 3)
+ assertTrue(production.contains(resources2Stones))
+ }
+
+ @Test
+ fun contains_singleFixedResource_moreThanEnough_amongOthers() {
+ val production = Production()
+ production.addFixedResource(ResourceType.STONE, 3)
+ production.addFixedResource(ResourceType.CLAY, 2)
+ assertTrue(production.contains(resources2Stones))
+ }
+
+ @Test
+ fun contains_multipleFixedResources_notEnoughOfOne() {
+ val production = Production()
+ production.addFixedResource(ResourceType.STONE, 3)
+ production.addFixedResource(ResourceType.CLAY, 1)
+ assertFalse(production.contains(resources2Stones3Clay))
+ }
+
+ @Test
+ fun contains_multipleFixedResources_notEnoughOfBoth() {
+ val production = Production()
+ production.addFixedResource(ResourceType.STONE, 1)
+ production.addFixedResource(ResourceType.CLAY, 1)
+ assertFalse(production.contains(resources2Stones3Clay))
+ }
+
+ @Test
+ fun contains_multipleFixedResources_moreThanEnough() {
+ val production = Production()
+ production.addFixedResource(ResourceType.STONE, 3)
+ production.addFixedResource(ResourceType.CLAY, 5)
+ assertTrue(production.contains(resources2Stones3Clay))
+ }
+
+ @Test
+ fun contains_singleChoice_containsEmpty() {
+ val production = Production()
+ production.addChoice(ResourceType.STONE, ResourceType.CLAY)
+ assertTrue(production.contains(emptyResources))
+ }
+
+ @Test
+ fun contains_singleChoice_enough() {
+ val production = Production()
+ production.addChoice(ResourceType.STONE, ResourceType.WOOD)
+ assertTrue(production.contains(resources1Wood))
+ assertTrue(production.contains(resources1Stone))
+ }
+
+ @Test
+ fun contains_multipleChoices_notBoth() {
+ val production = Production()
+ production.addChoice(ResourceType.STONE, ResourceType.CLAY)
+ production.addChoice(ResourceType.STONE, ResourceType.CLAY)
+ production.addChoice(ResourceType.STONE, ResourceType.CLAY)
+ assertFalse(production.contains(resources2Stones3Clay))
+ }
+
+ @Test
+ fun contains_multipleChoices_enough() {
+ val production = Production()
+ production.addChoice(ResourceType.STONE, ResourceType.ORE)
+ production.addChoice(ResourceType.STONE, ResourceType.WOOD)
+ assertTrue(production.contains(resources1Stone1Wood))
+ }
+
+ @Test
+ fun contains_multipleChoices_enoughReverseOrder() {
+ val production = Production()
+ production.addChoice(ResourceType.STONE, ResourceType.WOOD)
+ production.addChoice(ResourceType.STONE, ResourceType.ORE)
+ assertTrue(production.contains(resources1Stone1Wood))
+ }
+
+ @Test
+ fun contains_multipleChoices_moreThanEnough() {
+ val production = Production()
+ production.addChoice(ResourceType.LOOM, ResourceType.GLASS, ResourceType.PAPYRUS)
+ production.addChoice(ResourceType.STONE, ResourceType.ORE)
+ production.addChoice(ResourceType.STONE, ResourceType.WOOD)
+ assertTrue(production.contains(resources1Stone1Wood))
+ }
+
+ @Test
+ fun contains_mixedFixedAndChoice_enough() {
+ val production = Production()
+ production.addFixedResource(ResourceType.WOOD, 1)
+ production.addChoice(ResourceType.STONE, ResourceType.WOOD)
+ assertTrue(production.contains(resources1Stone1Wood))
+ }
+
+ @Test
+ fun addAll_empty() {
+ val production = Production()
+ production.addAll(emptyResources)
+ assertTrue(production.contains(emptyResources))
+ }
+
+ @Test
+ fun addAll_singleResource() {
+ val production = Production()
+ production.addAll(resources1Stone)
+ assertTrue(production.contains(resources1Stone))
+ }
+
+ @Test
+ fun addAll_multipleResources() {
+ val production = Production()
+ production.addAll(resources2Stones3Clay)
+ assertTrue(production.contains(resources2Stones3Clay))
+ }
+
+ @Test
+ fun addAll_production_multipleFixedResources() {
+ val production = Production()
+ production.addAll(resources2Stones3Clay)
+
+ val production2 = Production()
+ production2.addAll(production)
+
+ assertTrue(production2.contains(resources2Stones3Clay))
+ }
+
+ @Test
+ fun addAll_production_multipleChoices() {
+ val production = Production()
+ production.addChoice(ResourceType.STONE, ResourceType.WOOD)
+ production.addChoice(ResourceType.STONE, ResourceType.ORE)
+
+ val production2 = Production()
+ production2.addAll(production)
+ assertTrue(production.contains(resources1Stone1Wood))
+ }
+
+ @Test
+ fun addAll_production_mixedFixedResourcesAndChoices() {
+ val production = Production()
+ production.addFixedResource(ResourceType.WOOD, 1)
+ production.addChoice(ResourceType.STONE, ResourceType.WOOD)
+
+ val production2 = Production()
+ production2.addAll(production)
+
+ assertTrue(production.contains(resources1Stone1Wood))
+ }
+
+ @Test
+ fun asChoices_empty() {
+ val production = Production()
+ assertTrue(production.asChoices().isEmpty())
+ }
+
+ @Test
+ fun asChoices_onlyChoices() {
+ val production = Production()
+ production.addChoice(ResourceType.STONE, ResourceType.WOOD)
+ production.addChoice(ResourceType.STONE, ResourceType.ORE)
+ production.addChoice(ResourceType.CLAY, ResourceType.LOOM, ResourceType.GLASS)
+ assertEquals(production.alternativeResources, production.asChoices())
+ }
+
+ @Test
+ fun asChoices_onlyFixed() {
+ val production = Production()
+ production.addFixedResource(ResourceType.WOOD, 1)
+ production.addFixedResource(ResourceType.CLAY, 2)
+
+ val expected = HashSet<Set<ResourceType>>()
+ expected.add(EnumSet.of(ResourceType.WOOD))
+ expected.add(EnumSet.of(ResourceType.CLAY))
+ expected.add(EnumSet.of(ResourceType.CLAY))
+
+ assertEquals(expected, production.asChoices())
+ }
+
+ @Test
+ fun asChoices_mixed() {
+ val production = Production()
+ production.addChoice(ResourceType.STONE, ResourceType.ORE)
+ production.addChoice(ResourceType.CLAY, ResourceType.LOOM, ResourceType.GLASS)
+ production.addFixedResource(ResourceType.WOOD, 1)
+ production.addFixedResource(ResourceType.CLAY, 2)
+
+ val expected = HashSet<Set<ResourceType>>()
+ expected.add(EnumSet.of(ResourceType.STONE, ResourceType.ORE))
+ expected.add(EnumSet.of(ResourceType.CLAY, ResourceType.LOOM, ResourceType.GLASS))
+ expected.add(EnumSet.of(ResourceType.WOOD))
+ expected.add(EnumSet.of(ResourceType.CLAY))
+ expected.add(EnumSet.of(ResourceType.CLAY))
+
+ assertEquals(expected, production.asChoices())
+ }
+
+ @Test
+ fun equals_falseWhenNull() {
+ val production = Production()
+ production.addFixedResource(ResourceType.GLASS, 1)
+ production.addChoice(ResourceType.ORE, ResourceType.WOOD)
+
+ assertFalse(production == null)
+ }
+
+ @Test
+ fun equals_falseWhenDifferentClass() {
+ val production = Production()
+ production.addFixedResource(ResourceType.GLASS, 1)
+ val resources = Resources()
+ resources.add(ResourceType.GLASS, 1)
+
+ assertFalse(production == resources)
+ }
+
+ @Test
+ fun equals_trueWhenSame() {
+ val production = Production()
+ assertEquals(production, production)
+ }
+
+ @Test
+ fun equals_trueWhenSameContent() {
+ val production1 = Production()
+ val production2 = Production()
+ assertTrue(production1 == production2)
+ production1.addFixedResource(ResourceType.GLASS, 1)
+ production2.addFixedResource(ResourceType.GLASS, 1)
+ assertTrue(production1 == production2)
+ production1.addChoice(ResourceType.ORE, ResourceType.WOOD)
+ production2.addChoice(ResourceType.ORE, ResourceType.WOOD)
+ assertTrue(production1 == production2)
+ }
+
+ @Test
+ fun hashCode_sameWhenSameContent() {
+ val production1 = Production()
+ val production2 = Production()
+ assertEquals(production1.hashCode().toLong(), production2.hashCode().toLong())
+ production1.addFixedResource(ResourceType.GLASS, 1)
+ production2.addFixedResource(ResourceType.GLASS, 1)
+ assertEquals(production1.hashCode().toLong(), production2.hashCode().toLong())
+ production1.addChoice(ResourceType.ORE, ResourceType.WOOD)
+ production2.addChoice(ResourceType.ORE, ResourceType.WOOD)
+ assertEquals(production1.hashCode().toLong(), production2.hashCode().toLong())
+ }
+}
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactionsTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactionsTest.kt
new file mode 100644
index 00000000..11a03cd4
--- /dev/null
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactionsTest.kt
@@ -0,0 +1,36 @@
+package org.luxons.sevenwonders.game.resources
+
+import java.util.ArrayList
+import java.util.HashSet
+
+import org.junit.Test
+import org.luxons.sevenwonders.game.test.*
+
+import org.junit.Assert.assertEquals
+
+class ResourceTransactionsTest {
+
+ @Test
+ fun toTransactions() {
+ val transactionList = ArrayList<ResourceTransaction>()
+ transactionList.add(createTransaction(Provider.LEFT_PLAYER, ResourceType.WOOD))
+ transactionList.add(createTransaction(Provider.LEFT_PLAYER, ResourceType.CLAY))
+ transactionList.add(createTransaction(Provider.RIGHT_PLAYER, ResourceType.WOOD))
+
+ val transactions = ResourceTransactions(transactionList)
+
+ val expectedNormalized = HashSet<ResourceTransaction>()
+ expectedNormalized.add(
+ createTransaction(Provider.LEFT_PLAYER, ResourceType.WOOD, ResourceType.CLAY)
+ )
+ expectedNormalized.add(createTransaction(Provider.RIGHT_PLAYER, ResourceType.WOOD))
+
+ assertEquals(expectedNormalized, HashSet(transactions.toTransactions()))
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun remove_failsIfNoResourceForThatProvider() {
+ val transactions = ResourceTransactions()
+ transactions.remove(Provider.LEFT_PLAYER, Resources.of(ResourceType.WOOD))
+ }
+}
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourcesTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourcesTest.kt
new file mode 100644
index 00000000..72419fe3
--- /dev/null
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourcesTest.kt
@@ -0,0 +1,482 @@
+package org.luxons.sevenwonders.game.resources
+
+import org.junit.Assert.*
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.ExpectedException
+import java.util.NoSuchElementException
+
+class ResourcesTest {
+
+ @JvmField
+ @Rule
+ var thrown = ExpectedException.none()
+
+ @Test
+ fun init_shouldBeEmpty() {
+ val resources = Resources()
+ for (resourceType in ResourceType.values()) {
+ assertEquals(0, resources.getQuantity(resourceType).toLong())
+ }
+ assertEquals(0, resources.size().toLong())
+ assertTrue(resources.isEmpty)
+ }
+
+ @Test
+ fun add_zero() {
+ val resources = Resources()
+ resources.add(ResourceType.CLAY, 0)
+ assertEquals(0, resources.getQuantity(ResourceType.CLAY).toLong())
+ assertEquals(0, resources.size().toLong())
+ assertTrue(resources.isEmpty)
+ }
+
+ @Test
+ fun add_simple() {
+ val resources = Resources()
+ resources.add(ResourceType.WOOD, 3)
+ assertEquals(3, resources.getQuantity(ResourceType.WOOD).toLong())
+ assertEquals(3, resources.size().toLong())
+ assertFalse(resources.isEmpty)
+ }
+
+ @Test
+ fun add_multipleCallsStacked() {
+ val resources = Resources()
+ resources.add(ResourceType.ORE, 3)
+ resources.add(ResourceType.ORE, 2)
+ assertEquals(5, resources.getQuantity(ResourceType.ORE).toLong())
+ assertEquals(5, resources.size().toLong())
+ assertFalse(resources.isEmpty)
+ }
+
+ @Test
+ fun add_interlaced() {
+ val resources = Resources()
+ resources.add(ResourceType.GLASS, 3)
+ resources.add(ResourceType.STONE, 1)
+ resources.add(ResourceType.WOOD, 4)
+ resources.add(ResourceType.GLASS, 2)
+ assertEquals(5, resources.getQuantity(ResourceType.GLASS).toLong())
+ assertEquals(10, resources.size().toLong())
+ assertFalse(resources.isEmpty)
+ }
+
+ @Test
+ fun remove_some() {
+ val resources = Resources()
+ resources.add(ResourceType.WOOD, 3)
+ resources.remove(ResourceType.WOOD, 2)
+ assertEquals(1, resources.getQuantity(ResourceType.WOOD).toLong())
+ assertEquals(1, resources.size().toLong())
+ assertFalse(resources.isEmpty)
+ }
+
+ @Test
+ fun remove_all() {
+ val resources = Resources()
+ resources.add(ResourceType.WOOD, 3)
+ resources.remove(ResourceType.WOOD, 3)
+ assertEquals(0, resources.getQuantity(ResourceType.WOOD).toLong())
+ assertEquals(0, resources.size().toLong())
+ assertTrue(resources.isEmpty)
+ }
+
+ @Test
+ fun remove_tooMany() {
+ val resources = Resources()
+ resources.add(ResourceType.WOOD, 2)
+
+ thrown.expect(NoSuchElementException::class.java)
+ resources.remove(ResourceType.WOOD, 3)
+ }
+
+ @Test
+ fun addAll_empty() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 1)
+ resources.add(ResourceType.CLAY, 3)
+
+ val emptyResources = Resources()
+
+ resources.addAll(emptyResources)
+ assertEquals(1, resources.getQuantity(ResourceType.STONE).toLong())
+ assertEquals(3, resources.getQuantity(ResourceType.CLAY).toLong())
+ assertEquals(0, resources.getQuantity(ResourceType.ORE).toLong())
+ assertEquals(0, resources.getQuantity(ResourceType.GLASS).toLong())
+ assertEquals(0, resources.getQuantity(ResourceType.LOOM).toLong())
+ assertEquals(4, resources.size().toLong())
+ assertFalse(resources.isEmpty)
+ }
+
+ @Test
+ fun addAll_zeros() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 1)
+ resources.add(ResourceType.CLAY, 3)
+
+ val emptyResources = Resources()
+ emptyResources.add(ResourceType.STONE, 0)
+ emptyResources.add(ResourceType.CLAY, 0)
+
+ resources.addAll(emptyResources)
+ assertEquals(1, resources.getQuantity(ResourceType.STONE).toLong())
+ assertEquals(3, resources.getQuantity(ResourceType.CLAY).toLong())
+ assertEquals(0, resources.getQuantity(ResourceType.ORE).toLong())
+ assertEquals(0, resources.getQuantity(ResourceType.GLASS).toLong())
+ assertEquals(0, resources.getQuantity(ResourceType.LOOM).toLong())
+ assertEquals(4, resources.size().toLong())
+ assertFalse(resources.isEmpty)
+ }
+
+ @Test
+ fun addAll_same() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 1)
+ resources.add(ResourceType.CLAY, 3)
+
+ val resources2 = Resources()
+ resources.add(ResourceType.STONE, 2)
+ resources.add(ResourceType.CLAY, 6)
+
+ resources.addAll(resources2)
+ assertEquals(3, resources.getQuantity(ResourceType.STONE).toLong())
+ assertEquals(9, resources.getQuantity(ResourceType.CLAY).toLong())
+ assertEquals(0, resources.getQuantity(ResourceType.ORE).toLong())
+ assertEquals(0, resources.getQuantity(ResourceType.GLASS).toLong())
+ assertEquals(0, resources.getQuantity(ResourceType.LOOM).toLong())
+ assertEquals(12, resources.size().toLong())
+ assertFalse(resources.isEmpty)
+ }
+
+ @Test
+ fun addAll_overlap() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 1)
+ resources.add(ResourceType.CLAY, 3)
+
+ val resources2 = Resources()
+ resources.add(ResourceType.CLAY, 6)
+ resources.add(ResourceType.ORE, 4)
+
+ resources.addAll(resources2)
+ assertEquals(1, resources.getQuantity(ResourceType.STONE).toLong())
+ assertEquals(9, resources.getQuantity(ResourceType.CLAY).toLong())
+ assertEquals(4, resources.getQuantity(ResourceType.ORE).toLong())
+ assertEquals(0, resources.getQuantity(ResourceType.GLASS).toLong())
+ assertEquals(0, resources.getQuantity(ResourceType.LOOM).toLong())
+ assertEquals(14, resources.size().toLong())
+ assertFalse(resources.isEmpty)
+ }
+
+ @Test
+ fun contains_emptyContainsEmpty() {
+ val emptyResources = Resources()
+ val emptyResources2 = Resources()
+ assertTrue(emptyResources.contains(emptyResources2))
+ }
+
+ @Test
+ fun contains_singleTypeContainsEmpty() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 1)
+
+ val emptyResources = Resources()
+
+ assertTrue(resources.contains(emptyResources))
+ }
+
+ @Test
+ fun contains_multipleTypesContainsEmpty() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 1)
+ resources.add(ResourceType.CLAY, 3)
+
+ val emptyResources = Resources()
+
+ assertTrue(resources.contains(emptyResources))
+ }
+
+ @Test
+ fun contains_self() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 1)
+ resources.add(ResourceType.CLAY, 3)
+
+ assertTrue(resources.contains(resources))
+ }
+
+ @Test
+ fun contains_allOfEachType() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 1)
+ resources.add(ResourceType.CLAY, 3)
+
+ val resources2 = Resources()
+ resources2.add(ResourceType.STONE, 1)
+ resources2.add(ResourceType.CLAY, 3)
+
+ assertTrue(resources.contains(resources2))
+ }
+
+ @Test
+ fun contains_someOfEachType() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 2)
+ resources.add(ResourceType.CLAY, 4)
+
+ val resources2 = Resources()
+ resources2.add(ResourceType.STONE, 1)
+ resources2.add(ResourceType.CLAY, 3)
+
+ assertTrue(resources.contains(resources2))
+ }
+
+ @Test
+ fun contains_someOfSomeTypes() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 2)
+ resources.add(ResourceType.CLAY, 4)
+
+ val resources2 = Resources()
+ resources2.add(ResourceType.CLAY, 3)
+
+ assertTrue(resources.contains(resources2))
+ }
+
+ @Test
+ fun contains_allOfSomeTypes() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 2)
+ resources.add(ResourceType.CLAY, 4)
+
+ val resources2 = Resources()
+ resources2.add(ResourceType.CLAY, 4)
+
+ assertTrue(resources.contains(resources2))
+ }
+
+ @Test
+ fun minus_empty() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 1)
+ resources.add(ResourceType.CLAY, 3)
+
+ val emptyResources = Resources()
+
+ val diff = resources.minus(emptyResources)
+ assertEquals(1, diff.getQuantity(ResourceType.STONE).toLong())
+ assertEquals(3, diff.getQuantity(ResourceType.CLAY).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.ORE).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.GLASS).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.LOOM).toLong())
+ }
+
+ @Test
+ fun minus_self() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 1)
+ resources.add(ResourceType.CLAY, 3)
+
+ val diff = resources.minus(resources)
+ assertEquals(0, diff.getQuantity(ResourceType.STONE).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.CLAY).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.ORE).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.GLASS).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.LOOM).toLong())
+ }
+
+ @Test
+ fun minus_allOfEachType() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 1)
+ resources.add(ResourceType.CLAY, 3)
+
+ val resources2 = Resources()
+ resources2.add(ResourceType.STONE, 1)
+ resources2.add(ResourceType.CLAY, 3)
+
+ val diff = resources.minus(resources2)
+ assertEquals(0, diff.getQuantity(ResourceType.STONE).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.CLAY).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.ORE).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.GLASS).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.LOOM).toLong())
+ }
+
+ @Test
+ fun minus_someOfEachType() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 2)
+ resources.add(ResourceType.CLAY, 4)
+
+ val resources2 = Resources()
+ resources2.add(ResourceType.STONE, 1)
+ resources2.add(ResourceType.CLAY, 3)
+
+ val diff = resources.minus(resources2)
+ assertEquals(1, diff.getQuantity(ResourceType.STONE).toLong())
+ assertEquals(1, diff.getQuantity(ResourceType.CLAY).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.ORE).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.GLASS).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.LOOM).toLong())
+ }
+
+ @Test
+ fun minus_someOfSomeTypes() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 2)
+ resources.add(ResourceType.CLAY, 4)
+
+ val resources2 = Resources()
+ resources2.add(ResourceType.CLAY, 3)
+
+ val diff = resources.minus(resources2)
+ assertEquals(2, diff.getQuantity(ResourceType.STONE).toLong())
+ assertEquals(1, diff.getQuantity(ResourceType.CLAY).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.ORE).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.GLASS).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.LOOM).toLong())
+ }
+
+ @Test
+ fun minus_allOfSomeTypes() {
+ val resources = Resources()
+ resources.add(ResourceType.STONE, 2)
+ resources.add(ResourceType.CLAY, 4)
+
+ val resources2 = Resources()
+ resources2.add(ResourceType.CLAY, 4)
+
+ val diff = resources.minus(resources2)
+ assertEquals(2, diff.getQuantity(ResourceType.STONE).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.CLAY).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.ORE).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.GLASS).toLong())
+ assertEquals(0, diff.getQuantity(ResourceType.LOOM).toLong())
+ }
+
+ @Test
+ fun minus_tooMuchOfExistingType() {
+ val resources = Resources()
+ resources.add(ResourceType.CLAY, 4)
+
+ val resources2 = Resources()
+ resources2.add(ResourceType.CLAY, 5)
+
+ val diff = resources.minus(resources2)
+ assertEquals(0, diff.getQuantity(ResourceType.CLAY).toLong())
+ }
+
+ @Test
+ fun minus_someOfAnAbsentType() {
+ val resources = Resources()
+
+ val resources2 = Resources()
+ resources2.add(ResourceType.LOOM, 5)
+
+ val diff = resources.minus(resources2)
+ assertEquals(0, diff.getQuantity(ResourceType.LOOM).toLong())
+ }
+
+ @Test
+ fun minus_someOfATypeWithZero() {
+ val resources = Resources()
+ resources.add(ResourceType.LOOM, 0)
+
+ val resources2 = Resources()
+ resources2.add(ResourceType.LOOM, 5)
+
+ val diff = resources.minus(resources2)
+ assertEquals(0, diff.getQuantity(ResourceType.LOOM).toLong())
+ }
+
+ @Test
+ fun isEmpty_noElement() {
+ val resources = Resources()
+ assertTrue(resources.isEmpty)
+ }
+
+ @Test
+ fun isEmpty_singleZeroElement() {
+ val resources = Resources()
+ resources.add(ResourceType.LOOM, 0)
+ assertTrue(resources.isEmpty)
+ }
+
+ @Test
+ fun isEmpty_multipleZeroElements() {
+ val resources = Resources()
+ resources.add(ResourceType.WOOD, 0)
+ resources.add(ResourceType.ORE, 0)
+ resources.add(ResourceType.LOOM, 0)
+ assertTrue(resources.isEmpty)
+ }
+
+ @Test
+ fun isEmpty_singleElementMoreThanZero() {
+ val resources = Resources()
+ resources.add(ResourceType.LOOM, 3)
+ assertFalse(resources.isEmpty)
+ }
+
+ @Test
+ fun isEmpty_mixedZeroAndNonZeroElements() {
+ val resources = Resources()
+ resources.add(ResourceType.WOOD, 0)
+ resources.add(ResourceType.LOOM, 3)
+ assertFalse(resources.isEmpty)
+ }
+
+ @Test
+ fun isEmpty_mixedZeroAndNonZeroElements_reverseOrder() {
+ val resources = Resources()
+ resources.add(ResourceType.ORE, 3)
+ resources.add(ResourceType.PAPYRUS, 0)
+ assertFalse(resources.isEmpty)
+ }
+
+ @Test
+ fun equals_falseWhenNull() {
+ val resources = Resources()
+ resources.add(ResourceType.GLASS, 1)
+
+ assertFalse(resources == null)
+ }
+
+ @Test
+ fun equals_falseWhenDifferentClass() {
+ val resources = Resources()
+ resources.add(ResourceType.GLASS, 1)
+ val production = Production()
+ production.addFixedResource(ResourceType.GLASS, 1)
+
+ assertFalse(resources == production)
+ }
+
+ @Test
+ fun equals_trueWhenSame() {
+ val resources = Resources()
+ assertEquals(resources, resources)
+ }
+
+ @Test
+ fun equals_trueWhenSameContent() {
+ val resources1 = Resources()
+ val resources2 = Resources()
+ assertTrue(resources1 == resources2)
+ resources1.add(ResourceType.GLASS, 1)
+ resources2.add(ResourceType.GLASS, 1)
+ assertTrue(resources1 == resources2)
+ }
+
+ @Test
+ fun hashCode_sameWhenSameContent() {
+ val resources1 = Resources()
+ val resources2 = Resources()
+ assertEquals(resources1.hashCode().toLong(), resources2.hashCode().toLong())
+ resources1.add(ResourceType.GLASS, 1)
+ resources2.add(ResourceType.GLASS, 1)
+ assertEquals(resources1.hashCode().toLong(), resources2.hashCode().toLong())
+ }
+}
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/TradingRulesTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/TradingRulesTest.kt
new file mode 100644
index 00000000..859c997a
--- /dev/null
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/TradingRulesTest.kt
@@ -0,0 +1,127 @@
+package org.luxons.sevenwonders.game.resources
+
+import java.util.ArrayList
+
+import org.junit.experimental.theories.DataPoints
+import org.junit.experimental.theories.Theories
+import org.junit.experimental.theories.Theory
+import org.junit.runner.RunWith
+import org.luxons.sevenwonders.game.test.*
+
+import org.junit.Assert.assertEquals
+import org.junit.Assume.assumeTrue
+
+@RunWith(Theories::class)
+class TradingRulesTest {
+
+ @Theory
+ fun setCost_overridesCost(
+ defaultCost: Int, overriddenCost: Int, overriddenProvider: Provider,
+ provider: Provider, type: ResourceType
+ ) {
+ assumeTrue(defaultCost != overriddenCost)
+ assumeTrue(overriddenProvider != provider)
+
+ val rules = TradingRules(defaultCost)
+ rules.setCost(type, overriddenProvider, overriddenCost)
+
+ assertEquals(overriddenCost.toLong(), rules.getCost(type, overriddenProvider).toLong())
+ assertEquals(defaultCost.toLong(), rules.getCost(type, provider).toLong())
+ }
+
+ @Theory
+ fun computeCost_zeroForNoResources(defaultCost: Int) {
+ val rules = TradingRules(defaultCost)
+ assertEquals(0, rules.computeCost(ResourceTransactions()).toLong())
+ }
+
+ @Theory
+ fun computeCost_defaultCostWhenNoOverride(defaultCost: Int, provider: Provider, type: ResourceType) {
+ val rules = TradingRules(defaultCost)
+ val transactions = createTransactions(provider, type)
+ assertEquals(defaultCost.toLong(), rules.computeCost(transactions).toLong())
+ }
+
+ @Theory
+ fun computeCost_twiceDefaultFor2Resources(defaultCost: Int, provider: Provider, type: ResourceType) {
+ val rules = TradingRules(defaultCost)
+ val transactions = createTransactions(provider, type, type)
+ assertEquals((2 * defaultCost).toLong(), rules.computeCost(transactions).toLong())
+ }
+
+ @Theory
+ fun computeCost_overriddenCost(defaultCost: Int, overriddenCost: Int, provider: Provider, type: ResourceType) {
+ val rules = TradingRules(defaultCost)
+ rules.setCost(type, provider, overriddenCost)
+ val transactions = createTransactions(provider, type)
+ assertEquals(overriddenCost.toLong(), rules.computeCost(transactions).toLong())
+ }
+
+ @Theory
+ fun computeCost_defaultCostWhenOverrideOnOtherProviderOrType(
+ defaultCost: Int, overriddenCost: Int,
+ overriddenProvider: Provider,
+ overriddenType: ResourceType, provider: Provider,
+ type: ResourceType
+ ) {
+ assumeTrue(overriddenProvider != provider || overriddenType != type)
+ val rules = TradingRules(defaultCost)
+ rules.setCost(overriddenType, overriddenProvider, overriddenCost)
+ val transactions = createTransactions(provider, type)
+ assertEquals(defaultCost.toLong(), rules.computeCost(transactions).toLong())
+ }
+
+ @Theory
+ fun computeCost_oneDefaultAndOneOverriddenType(
+ defaultCost: Int, overriddenCost: Int,
+ overriddenType: ResourceType, provider: Provider,
+ type: ResourceType
+ ) {
+ assumeTrue(overriddenType != type)
+ val rules = TradingRules(defaultCost)
+ rules.setCost(overriddenType, provider, overriddenCost)
+ val transactions = createTransactions(provider, overriddenType, type)
+ assertEquals((defaultCost + overriddenCost).toLong(), rules.computeCost(transactions).toLong())
+ }
+
+ @Theory
+ fun computeCost_oneDefaultAndOneOverriddenProvider(
+ defaultCost: Int, overriddenCost: Int,
+ overriddenProvider: Provider, provider: Provider,
+ type: ResourceType
+ ) {
+ assumeTrue(overriddenProvider != provider)
+ val rules = TradingRules(defaultCost)
+ rules.setCost(type, overriddenProvider, overriddenCost)
+
+ val boughtResources = ArrayList<ResourceTransaction>(2)
+ boughtResources.add(createTransaction(provider, type))
+ boughtResources.add(createTransaction(overriddenProvider, type))
+
+ assertEquals(
+ (defaultCost + overriddenCost).toLong(),
+ rules.computeCost(ResourceTransactions(boughtResources)).toLong()
+ )
+ }
+
+ companion object {
+
+ @JvmStatic
+ @DataPoints
+ fun costs(): IntArray {
+ return intArrayOf(0, 1, 2)
+ }
+
+ @JvmStatic
+ @DataPoints
+ fun providers(): Array<Provider> {
+ return Provider.values()
+ }
+
+ @JvmStatic
+ @DataPoints
+ fun resourceTypes(): Array<ResourceType> {
+ return ResourceType.values()
+ }
+ }
+}
bgstack15