Gamelib/src/test/java/uulm/teamname/marvelous/gamelibrary/json/ingame/deserialize/EntityDeserializerTest.java

322 lines
12 KiB
Java

package uulm.teamname.marvelous.gamelibrary.json.ingame.deserialize;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.InjectableValues;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.Test;
import uulm.teamname.marvelous.gamelibrary.IntVector2;
import uulm.teamname.marvelous.gamelibrary.entities.*;
import uulm.teamname.marvelous.gamelibrary.entities.Character;
import uulm.teamname.marvelous.gamelibrary.config.CharacterConfig;
import uulm.teamname.marvelous.gamelibrary.config.CharacterProperties;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.ThreadLocalRandom;
class EntityDeserializerTest {
ObjectMapper mapper;
HashMap<String, CharacterProperties> propertiesMap;
@BeforeEach
void setUp() {
mapper = new ObjectMapper();
propertiesMap = new HashMap<>();
var config = mock(CharacterConfig.class);
when(config.getMap()).thenReturn(propertiesMap);
mapper.setInjectableValues(new InjectableValues
.Std()
.addValue("CharacterConfig", config));
}
@Test
void simpleCharacterTest() throws JsonProcessingException {
var characterProperties = new CharacterProperties();
characterProperties.attackRange = 12;
characterProperties.rangedDamage = 13;
characterProperties.meleeDamage = 14;
propertiesMap.put("God", characterProperties);
var character = new Character(
new EntityID(EntityType.P1, 3),
new IntVector2(4, 2),
"God",
255,
65535,
4,
12,
13,
14
);
character.inventory.addStone(StoneType.MindStone);
character.inventory.addStone(StoneType.SoulStone);
var jsonRepresentingCharacter = """
{
"entityType": "Character",
"name": "God",
"PID": 1,
"ID": 3,
"HP": 255,
"MP": 65535,
"AP": 4,
"stones": [1, 5],
"position": [4, 2]
}
""";
assertThat((Character) mapper.readValue(jsonRepresentingCharacter, Entity.class))
.isEqualTo(character);
}
@Test
void simpleInfinityStoneTest() throws JsonProcessingException {
var infinityStone = new InfinityStone(
new EntityID(EntityType.InfinityStones, 2),
new IntVector2(98765, 43210),
StoneType.RealityStone
);
var jsonRepresentingInfinityStone = """
{
"entityType": "InfinityStone",
"ID": 2,
"position": [98765, 43210]
}
""";
assertThat((InfinityStone) mapper.readValue(jsonRepresentingInfinityStone, Entity.class))
.isEqualTo(infinityStone);
}
@Test
void simpleRockTest() throws JsonProcessingException {
var rock = new Rock(
new EntityID(EntityType.Rocks, 324985),
new IntVector2(12357, 1371113),
86420
);
var jsonRepresentingRock = """
{
"entityType": "Rock",
"ID": 324985,
"HP": 86420,
"position": [12357, 1371113]
}
""";
assertThat(mapper.readValue(jsonRepresentingRock, Rock.class))
.isEqualTo(rock);
}
/**
* Random tests to see if the deserialization actually works
*/
@Test
void randomTests() throws JsonProcessingException {
// Get the randoms
Iterator<Integer> randomIntegers = ThreadLocalRandom.current().ints().iterator();
int repetitions = 1000;
// Initialize as StringBuilder for performance
StringBuilder characterName = new StringBuilder();
for (int i = 0; i < repetitions; i++) {
// Get a random character name based on weird strings
int nameLength = Math.abs(randomIntegers.next() % 12);
for (int j = 0; j < (nameLength) + 3; j++) {
// append char between A and Z, and make lowercase 50% of the time
characterName.append((char) (
(65 + Math.abs(randomIntegers.next() % 26))
+ 32 * Math.abs(randomIntegers.next() % 2)
));
}
// Generate a random character
int attackRange = Math.abs(randomIntegers.next());
int rangedDamage = Math.abs(randomIntegers.next());
int meleeDamage = Math.abs(randomIntegers.next());
var characterProperties = new CharacterProperties();
characterProperties.name = characterName.toString();
characterProperties.attackRange = attackRange;
characterProperties.rangedDamage = rangedDamage;
characterProperties.meleeDamage = meleeDamage;
propertiesMap.put(characterName.toString(), characterProperties);
Character character = new Character(
new EntityID(
randomIntegers.next() % 2 == 0 ? EntityType.P1 : EntityType.P2,
Math.abs(randomIntegers.next() % 6)),
new IntVector2(Math.abs(randomIntegers.next()), Math.abs(randomIntegers.next())),
characterName.toString(),
Math.abs(randomIntegers.next()),
Math.abs(randomIntegers.next()),
Math.abs(randomIntegers.next()),
attackRange,
rangedDamage,
meleeDamage
);
// give the character 0 to 5 infinity stones randomly
int characterInfinityStoneCount = Math.abs(randomIntegers.next()) % 6;
HashSet<Integer> usedStones = new HashSet<>(14);
for (int j = 0; j < characterInfinityStoneCount; j++) {
int currentStone;
do {
currentStone = Math.abs(randomIntegers.next() % 6);
} while (!usedStones.add(currentStone));
character.inventory.addStone(StoneType.valueOf(currentStone));
}
// create a string representing the character's current inventory state
String characterInventoryStringRepresentation = "";
for (Iterator<StoneType> it = character.inventory.iterator(); it.hasNext(); ) {
characterInventoryStringRepresentation += it.next().getID() + (it.hasNext() ? ", " : "");
}
// create the actual JSON representation of the character
String jsonRepresentingCharacter = """
{
"entityType": "Character",
"name": "%s",
"PID": %s,
"ID": %d,
"HP": %d,
"MP": %d,
"AP": %d,
"stones": [%s],
"position": [%d, %d]
}
""".formatted( // formatting the string with all required values
character.name,
character.id.type.toString().charAt(1), // Take the second char from P1 and P2
character.id.id,
character.hp.getValue(),
character.mp.getValue(),
character.ap.getValue(),
characterInventoryStringRepresentation,
character.getPosition().getX(),
character.getPosition().getY()
);
// === RANDOM INFINITY STONE ===
int infinityStoneID = Math.abs(randomIntegers.next() % 6); // get the InfinityStoneID here for Enum conversion
InfinityStone stone = new InfinityStone(
new EntityID(
EntityType.InfinityStones,
infinityStoneID),
new IntVector2(Math.abs(randomIntegers.next()), Math.abs(randomIntegers.next())),
StoneType.valueOf(infinityStoneID)
);
// create the JSON representation of the InfinityStone
String jsonRepresentingStone = """
{
"entityType": "InfinityStone",
"ID": %d,
"position": [%d, %d]
}
""".formatted( // formatting the string with the required values. Less this time, luckily
stone.id.id,
stone.getPosition().getX(),
stone.getPosition().getY()
);
// === RANDOM ROCK ===
Rock rock = new Rock(
new EntityID(
EntityType.Rocks,
Math.abs(randomIntegers.next())),
new IntVector2(Math.abs(randomIntegers.next()), Math.abs(randomIntegers.next())),
Math.abs(randomIntegers.next())
);
// create the JSON representing Rock
String jsonRepresentingRock = """
{
"entityType": "Rock",
"ID": %d,
"HP": %d,
"position": [%d, %d]
}
""".formatted(// formatting the string with the required arguments
rock.id.id,
rock.getHp(),
rock.getPosition().getX(),
rock.getPosition().getY()
);
// === RANDOM PORTAL ===
Portal portal = new Portal(
new EntityID(EntityType.Portals, Math.abs(randomIntegers.next())),
new IntVector2(Math.abs(randomIntegers.next()), Math.abs(randomIntegers.next()))
);
String jsonRepresentingPortal = """
{
"entityType": "Portal",
"ID": %d,
"position": [%d, %d]
}
""".formatted(// formatting the string with the required arguments
portal.id.id,
portal.getPosition().getX(),
portal.getPosition().getY()
);
// System.out.println(character);
// System.out.println(jsonRepresentingCharacter);
// System.out.println(stone);
// System.out.println(jsonRepresentingStone);
// System.out.println(rock);
// System.out.println(jsonRepresentingRock);
// System.out.println(portal);
// System.out.println(jsonRepresentingPortal);
// // Assertions
assertThat((Character) (mapper.readValue(jsonRepresentingCharacter, Entity.class)))
.isEqualTo(character);
assertThat((InfinityStone) (mapper.readValue(jsonRepresentingStone, Entity.class)))
.isEqualTo(stone);
assertThat((Rock) (mapper.readValue(jsonRepresentingRock, Entity.class)))
.isEqualTo(rock);
assertThat((Portal) mapper.readValue(jsonRepresentingPortal, Entity.class))
.isEqualTo(portal);
characterName.setLength(0); // empty the StringBuilder
}
}
}