FIX cardDB implementation (and corresponding Tests) for a bug not accounting for too-strict art preference policy for some cards.

This commit is contained in:
leriomaggio
2021-07-26 11:31:11 +01:00
parent cc3cafa964
commit 04ae8fc28a
3 changed files with 160 additions and 50 deletions

View File

@@ -612,10 +612,20 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
return artPref.accept(ed); return artPref.accept(ed);
} }
})); }));
/* At this point, it may be possible that Art Preference is too-strict for the requested card!
i.e. acceptedEditions.size() == 0!
This may be the case of Cards Only available in NON-CORE/EXPANSIONS/REPRINT sets.
(NOTE: We've already checked that any print of the request card exists in the DB)
If this happens, we won't try to iterate over an empty list. Instead, we will fall back
to original lists of editions (unfiltered, of course) AND STILL sorted according to chosen art preference.
*/
if (acceptedEditions.size() == 0)
acceptedEditions.addAll(cardEditions);
Collections.sort(acceptedEditions); // CardEdition correctly sort by (release) date Collections.sort(acceptedEditions); // CardEdition correctly sort by (release) date
if (artPref.latestFirst) if (artPref.latestFirst)
Collections.reverse(acceptedEditions); // newest editions first Collections.reverse(acceptedEditions); // newest editions first
PaperCard candidate = null; PaperCard candidate = null;
for (CardEdition ed : acceptedEditions) { for (CardEdition ed : acceptedEditions) {
PaperCard cardFromSet = getCardFromSet(cr.cardName, ed, artIndex, cr.isFoil); PaperCard cardFromSet = getCardFromSet(cr.cardName, ed, artIndex, cr.isFoil);

View File

@@ -15,57 +15,57 @@ import static org.testng.Assert.*;
public class CardDbTestCase extends ForgeCardMockTestCase { public class CardDbTestCase extends ForgeCardMockTestCase {
private LegacyCardDb legacyCardDb; protected LegacyCardDb legacyCardDb;
private CardDb cardDb; protected CardDb cardDb;
// Shivan Dragon is great as it has multiple arts from re-prints // Shivan Dragon is great as it has multiple arts from re-prints
private final String cardNameShivanDragon = "Shivan Dragon"; protected final String cardNameShivanDragon = "Shivan Dragon";
private final String editionShivanDragon = "2ED"; protected final String editionShivanDragon = "2ED";
private final String collNrShivanDragon = "175"; protected final String collNrShivanDragon = "175";
// Test Foil case - first foil ever printed! // Test Foil case - first foil ever printed!
private final String cardNameFoilLightningDragon = "Lightning Dragon+"; protected final String cardNameFoilLightningDragon = "Lightning Dragon+";
private final String cardNameLightningDragon = "Lightning Dragon"; protected final String cardNameLightningDragon = "Lightning Dragon";
private final String editionLightningDragon = "PUSG"; protected final String editionLightningDragon = "PUSG";
private final String collNrLightningDragon = "202"; protected final String collNrLightningDragon = "202";
// Get a card with multiple arts // Get a card with multiple arts
private final String cardNameHymnToTourach = "Hymn to Tourach"; // good 'ol hymn w/ four different art protected final String cardNameHymnToTourach = "Hymn to Tourach"; // good 'ol hymn w/ four different art
private final String[] collectorNumbersHymnToTourach = {"38a", "38b", "38c", "38d"}; protected final String[] collectorNumbersHymnToTourach = {"38a", "38b", "38c", "38d"};
private final String editionHymnToTourach = "FEM"; protected final String editionHymnToTourach = "FEM";
//Get Card From Editions Test fixtures //Get Card From Editions Test fixtures
private final String oldFrameShivanDragonEdition = "LEA"; protected final String oldFrameShivanDragonEdition = "LEA";
private final String newFrameShivanDragonEdition = "M20"; protected final String newFrameShivanDragonEdition = "M20";
private final String oldFrameLightningDragonEdition = "USG"; protected final String oldFrameLightningDragonEdition = "USG";
private final String oldFrameLightningDragonEditionNoPromo = "USG"; protected final String oldFrameLightningDragonEditionNoPromo = "USG";
private final String newFrameLightningDragonEdition = "VMA"; protected final String newFrameLightningDragonEdition = "VMA";
private final String newFrameLightningDragonEditionNoPromo = "USG"; protected final String newFrameLightningDragonEditionNoPromo = "USG";
private final String newFrameHymnToTourachEdition = "EMA"; protected final String newFrameHymnToTourachEdition = "EMA";
private final String newFrameHymnToTourachEditionNoPromo = "EMA"; protected final String newFrameHymnToTourachEditionNoPromo = "EMA";
private final String oldFrameHymnToTourachEdition = "FEM"; protected final String oldFrameHymnToTourachEdition = "FEM";
private final String oldFrameHymnToTourachEditionNoPromo = "FEM"; protected final String oldFrameHymnToTourachEditionNoPromo = "FEM";
// Test Dates and Editions // Test Dates and Editions
private final String printedBeforeFromTheVaultDate = "2008-10-01"; protected final String printedBeforeFromTheVaultDate = "2008-10-01";
private final String latestFrameShivanDragonEditionBefore = "DRB"; protected final String latestFrameShivanDragonEditionBefore = "DRB";
private final String latestFrameShivanDragonEditionBeforeNoPromo = "10E"; protected final String latestFrameShivanDragonEditionBeforeNoPromo = "10E";
private final String latestFrameLightningDragonEditionBefore = "MBP"; protected final String latestFrameLightningDragonEditionBefore = "MBP";
private final String latestFrameLightningDragonEditionBeforeNoPromo = "USG"; protected final String latestFrameLightningDragonEditionBeforeNoPromo = "USG";
private final String printedBeforeEternalMasters = "2015-01-01"; protected final String printedBeforeEternalMasters = "2015-01-01";
private final String latestFrameHymnToTourachEditionBefore = "VMA"; protected final String latestFrameHymnToTourachEditionBefore = "VMA";
private final String latestFrameHymnToTourachEditionBeforeNoPromo = "FEM"; protected final String latestFrameHymnToTourachEditionBeforeNoPromo = "FEM";
// Get a card that has lots of editions so that we can test fetching for specific editions and print dates // Get a card that has lots of editions so that we can test fetching for specific editions and print dates
private final String cardNameCounterspell = "Counterspell"; protected final String cardNameCounterspell = "Counterspell";
private final String[] editionsCounterspell = {"3ED", "4ED", "ICE", "5ED", "TMP", "S99", "MMQ", "A25", "MH2"}; protected final String[] editionsCounterspell = {"3ED", "4ED", "ICE", "5ED", "TMP", "S99", "MMQ", "A25", "MH2"};
private final String counterspellPrintedBeforeMasters25 = "2018-03-15"; // One day before Master25 release protected final String counterspellPrintedBeforeMasters25 = "2018-03-15"; // One day before Master25 release
private final String[] counterspellLatestBeforeMasters25 = {"MPS_AKH", "EMA"}; protected final String[] counterspellLatestBeforeMasters25 = {"MPS_AKH", "EMA"};
private final String counterspellPrintedBeforeEternalMasters = "2016-06-09"; // One day before Eternal Masters release protected final String counterspellPrintedBeforeEternalMasters = "2016-06-09"; // One day before Eternal Masters release
private final String[] counterspellLatestBeforeEternalMasters = {"TPR", "7ED"}; protected final String[] counterspellLatestBeforeEternalMasters = {"TPR", "7ED"};
@BeforeMethod @BeforeMethod
public void setup(){ public void setup(){
@@ -1292,16 +1292,118 @@ public class CardDbTestCase extends ForgeCardMockTestCase {
assertEquals(this.cardDb.getCardArtPreference(), CardDb.CardArtPreference.LATEST_ART_ALL_EDITIONS); assertEquals(this.cardDb.getCardArtPreference(), CardDb.CardArtPreference.LATEST_ART_ALL_EDITIONS);
} }
@Test(enabled = false) /**
public void testCardsNotFoundWhileLoadingDecks(){ * This set is crucial to test Card Art Preference and Strict Policies.
String cardName = "Yavimaya, Cradle of Growth"; * In particular, we wish to test whether the DB is robust enough to retrieve
PaperCard cardInDb = this.cardDb.getCard(cardName); * the card even if Art Preference is too strict, that is: the card is only
assertNotNull(cardInDb); * available in Filtered sets.
assertEquals(cardInDb.getEdition(), "MH2"); *
* When this happens, we also want to be sure that retrieved card will be
* still compliant with Art Preference, when multiple candidates are possible
* (therefore, latest or original art first)
*
* For this test we will use the following card/editions as fixtures:
* - Militant Angel: ONLY available in forge in Game Night
* - Loyal Unicorn: Available in Forge in The List, and COMMANDER 2018
* - Selfless Squire: Available in Forge in COMMANDER 2021, Treasure Chest, and COMMANDER 2016
* - Atog: Test card available in Promo and Non-Promo Print. We will use this card as reference
* which will have multiple editions returned over the preference selections.
*/
@Test
public void testCardsAlwaysReturnedEvenIfCardArtPreferenceIsTooStrict(){
// REFERENCE CASE - NO FILTER
assertEquals(this.cardDb.getCardArtPreference(), CardDb.CardArtPreference.LATEST_ART_ALL_EDITIONS);
cardName = "Urza's Saga"; PaperCard atog = this.cardDb.getCard("Atog");
cardInDb = this.cardDb.getCard(cardName); assertNotNull(atog);
assertNotNull(cardInDb); assertEquals(atog.getEdition(), "ME4"); // Game Night
PaperCard militantAngel = this.cardDb.getCard("Militant Angel");
assertNotNull(militantAngel);
assertEquals(militantAngel.getEdition(), "GNT"); // Game Night
// Loyal Unicorn: Available in Forge in The List and COMMANDER 2018
PaperCard loyalUnicorn = this.cardDb.getCard("Loyal Unicorn");
assertNotNull(loyalUnicorn);
assertEquals(loyalUnicorn.getEdition(), "PLIST"); // The List
// Selfless Squire: Available in Forge in COMMANDER 2021; Treasure Chest; COMMANDER 2016
PaperCard selflessSquire = this.cardDb.getCard("Selfless Squire");
assertNotNull(selflessSquire);
assertEquals(selflessSquire.getEdition(), "C21"); // The List
// Set Strictness to Expansions and Reprint Only (LATEST)
this.cardDb.setCardArtPreference(true, true);
assertEquals(this.cardDb.getCardArtPreference(), CardDb.CardArtPreference.LATEST_ART_CORE_EXPANSIONS_REPRINT_ONLY);
// ONLY CHANGE HERE IS FOR ATOG
atog = this.cardDb.getCard("Atog");
assertNotNull(atog);
assertEquals(atog.getEdition(), "MRD"); // Game Night
militantAngel = this.cardDb.getCard("Militant Angel");
assertNotNull(militantAngel);
assertEquals(militantAngel.getEdition(), "GNT"); // Game Night
// Loyal Unicorn: Available in Forge in The List and COMMANDER 2018
loyalUnicorn = this.cardDb.getCard("Loyal Unicorn");
assertNotNull(loyalUnicorn);
assertEquals(loyalUnicorn.getEdition(), "PLIST"); // The List
// Selfless Squire: Available in Forge in COMMANDER 2021; Treasure Chest; COMMANDER 2016
selflessSquire = this.cardDb.getCard("Selfless Squire");
assertNotNull(selflessSquire);
assertEquals(selflessSquire.getEdition(), "C21"); // The List
// Set Strictness to ORIGINAL ART NO FILTER - Ref case
this.cardDb.setCardArtPreference(false, false);
assertEquals(this.cardDb.getCardArtPreference(), CardDb.CardArtPreference.ORIGINAL_ART_ALL_EDITIONS);
// ONLY CHANGE HERE IS FOR ATOG
atog = this.cardDb.getCard("Atog");
assertNotNull(atog);
assertEquals(atog.getEdition(), "ATQ"); // Game Night
militantAngel = this.cardDb.getCard("Militant Angel");
assertNotNull(militantAngel);
assertEquals(militantAngel.getEdition(), "GNT");
// Loyal Unicorn: Available in Forge in The List and COMMANDER 2018
loyalUnicorn = this.cardDb.getCard("Loyal Unicorn");
assertNotNull(loyalUnicorn);
assertEquals(loyalUnicorn.getEdition(), "C18");
// Selfless Squire: Available in Forge in COMMANDER 2021; Treasure Chest; COMMANDER 2016
selflessSquire = this.cardDb.getCard("Selfless Squire");
assertNotNull(selflessSquire);
assertEquals(selflessSquire.getEdition(), "C16");
// Set Strictness to ORIGINAL ART NO FILTER - Ref case
this.cardDb.setCardArtPreference(false, true);
assertEquals(this.cardDb.getCardArtPreference(), CardDb.CardArtPreference.ORIGINAL_ART_CORE_EXPANSIONS_REPRINT_ONLY);
// ONLY CHANGE HERE IS FOR ATOG
atog = this.cardDb.getCard("Atog");
assertNotNull(atog);
assertEquals(atog.getEdition(), "ATQ"); // Game Night
militantAngel = this.cardDb.getCard("Militant Angel");
assertNotNull(militantAngel);
assertEquals(militantAngel.getEdition(), "GNT");
// Loyal Unicorn: Available in Forge in The List and COMMANDER 2018
loyalUnicorn = this.cardDb.getCard("Loyal Unicorn");
assertNotNull(loyalUnicorn);
assertEquals(loyalUnicorn.getEdition(), "PLIST"); // This is returned as this is a REPRINT Set!!
// Selfless Squire: Available in Forge in COMMANDER 2021; Treasure Chest; COMMANDER 2016
selflessSquire = this.cardDb.getCard("Selfless Squire");
assertNotNull(selflessSquire);
assertEquals(selflessSquire.getEdition(), "C16");
// Set Art Preference back to default
this.cardDb.setCardArtPreference(true, false);
assertEquals(this.cardDb.getCardArtPreference(), CardDb.CardArtPreference.LATEST_ART_ALL_EDITIONS);
} }
} }

View File

@@ -5,7 +5,6 @@ import forge.ImageKeys;
import forge.Singletons; import forge.Singletons;
import forge.StaticData; import forge.StaticData;
import forge.gamesimulationtests.util.CardDatabaseHelper; import forge.gamesimulationtests.util.CardDatabaseHelper;
import forge.item.PaperCard;
import forge.localinstance.properties.ForgeConstants; import forge.localinstance.properties.ForgeConstants;
import forge.localinstance.properties.ForgePreferences; import forge.localinstance.properties.ForgePreferences;
import forge.model.FModel; import forge.model.FModel;
@@ -35,7 +34,7 @@ import java.util.ResourceBundle;
@SuppressStaticInitializationFor({"forge.ImageCache", "forge.localinstance.properties.ForgeConstants"}) @SuppressStaticInitializationFor({"forge.ImageCache", "forge.localinstance.properties.ForgeConstants"})
public class ForgeCardMockTestCase extends PowerMockTestCase { public class ForgeCardMockTestCase extends PowerMockTestCase {
private static String getUserDir() { protected static String getUserDir() {
// Adapted - reduced version from ForgeProfileProperties (which is private) // Adapted - reduced version from ForgeProfileProperties (which is private)
final String osName = System.getProperty("os.name"); final String osName = System.getProperty("os.name");
final String homeDir = System.getProperty("user.home"); final String homeDir = System.getProperty("user.home");
@@ -59,7 +58,7 @@ public class ForgeCardMockTestCase extends PowerMockTestCase {
return fallbackDataDir; return fallbackDataDir;
} }
private void initForgeConstants() throws IllegalAccessException { protected void initForgeConstants() throws IllegalAccessException {
PowerMockito.mockStatic(ForgeConstants.class); PowerMockito.mockStatic(ForgeConstants.class);
// Path Sep // Path Sep
Field fPathSep = PowerMockito.field(ForgeConstants.class, "PATH_SEPARATOR"); Field fPathSep = PowerMockito.field(ForgeConstants.class, "PATH_SEPARATOR");
@@ -132,7 +131,6 @@ public class ForgeCardMockTestCase extends PowerMockTestCase {
PowerMockito.mockStatic(ImageIO.class); PowerMockito.mockStatic(ImageIO.class);
PowerMockito.mockStatic(ImageCache.class); PowerMockito.mockStatic(ImageCache.class);
PowerMockito.mockStatic(ImageKeys.class); PowerMockito.mockStatic(ImageKeys.class);
PowerMockito.when(ImageKeys.hasImage(Mockito.any(PaperCard.class))).thenReturn(true);
initForgeConstants(); initForgeConstants();
//Mocking some more static stuff //Mocking some more static stuff