package org.ovirt.engine.core.utils.serialization.json; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Objects; import org.codehaus.jackson.map.DeserializationConfig; import org.codehaus.jackson.map.ObjectMapper; import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.ovirt.engine.api.extensions.ExtMap; import org.ovirt.engine.api.extensions.aaa.Authn; import org.ovirt.engine.core.common.businessentities.BusinessEntity; import org.ovirt.engine.core.common.businessentities.Role; import org.ovirt.engine.core.common.businessentities.StorageDomainDynamic; import org.ovirt.engine.core.common.businessentities.StorageDomainStatic; import org.ovirt.engine.core.common.businessentities.StorageDomainStatus; import org.ovirt.engine.core.common.businessentities.StoragePool; import org.ovirt.engine.core.common.businessentities.StoragePoolIsoMap; import org.ovirt.engine.core.common.businessentities.StoragePoolStatus; import org.ovirt.engine.core.common.businessentities.VDSStatus; import org.ovirt.engine.core.common.businessentities.VDSType; import org.ovirt.engine.core.common.businessentities.VdsDynamic; import org.ovirt.engine.core.common.businessentities.VdsSpmIdMap; import org.ovirt.engine.core.common.businessentities.VdsStatic; import org.ovirt.engine.core.common.businessentities.VdsStatistics; import org.ovirt.engine.core.common.businessentities.VdsTransparentHugePagesState; import org.ovirt.engine.core.common.businessentities.storage.StorageType; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.utils.MockConfigRule; import org.ovirt.engine.core.utils.RandomUtils; /** * This test is designed to test that our business entities can be serialized/deserialized by Jackson correctly. */ @RunWith(Parameterized.class) public class JsonObjectSerializationEntitiesTest { @Parameterized.Parameter public BusinessEntity<?> entity; @ClassRule public static MockConfigRule mcr = new MockConfigRule(); @Parameterized.Parameters public static Object[] data() { RandomUtils random = RandomUtils.instance(); VdsStatic vdsStatic = new VdsStatic(random.nextString(10), random.nextString(10), random.nextInt(), random.nextInt(), random.nextString(10), Guid.newGuid(), Guid.newGuid(), random.nextString(10), random.nextBoolean(), random.nextEnum(VDSType.class), Guid.newGuid()); return new Object[] { vdsStatic, randomVdsDynamic(), randomVdsStatistics(), new VdsSpmIdMap(Guid.newGuid(), Guid.newGuid(), random.nextInt()), randomStorageDomainStatic(), new StorageDomainDynamic(random.nextInt(), Guid.newGuid(), random.nextInt()), randomStoragePool(), new StoragePoolIsoMap(Guid.newGuid(), Guid.newGuid(), random.nextEnum(StorageDomainStatus.class)), randomRole(), new IdContainerClass<>(new VdsSpmIdMap(Guid.newGuid(), Guid.newGuid(), random.nextInt())), new IdContainerClass<>(Guid.newGuid()) }; } private static StoragePool randomStoragePool() { RandomUtils random = RandomUtils.instance(); StoragePool sp = new StoragePool(); sp.setdescription(random.nextString(10)); sp.setComment(random.nextString(10)); sp.setName(random.nextString(10)); sp.setId(Guid.newGuid()); sp.setIsLocal(random.nextBoolean()); sp.setStatus(random.nextEnum(StoragePoolStatus.class)); return sp; } private static StorageDomainStatic randomStorageDomainStatic() { RandomUtils random = RandomUtils.instance(); StorageDomainStatic sds = new StorageDomainStatic(); sds.setId(Guid.newGuid()); sds.setStorage(random.nextString(10)); sds.setStorageType(random.nextEnum(StorageType.class)); sds.setStorageName(random.nextString(10)); sds.setDescription(random.nextString(10)); sds.setWarningLowSpaceIndicator(5); sds.setCriticalSpaceActionBlocker(10); return sds; } private static VdsDynamic randomVdsDynamic() { RandomUtils random = RandomUtils.instance(); VdsDynamic vdsDynamic = new VdsDynamic(); vdsDynamic.setCpuCores(random.nextInt()); vdsDynamic.setCpuThreads(random.nextInt()); vdsDynamic.setCpuModel(random.nextString(10)); vdsDynamic.setCpuSpeedMh(random.nextDouble()); vdsDynamic.setIfTotalSpeed(random.nextString(10)); vdsDynamic.setKvmEnabled(random.nextBoolean()); vdsDynamic.setMemCommited(random.nextInt()); vdsDynamic.setPhysicalMemMb(random.nextInt()); vdsDynamic.setStatus(random.nextEnum(VDSStatus.class)); vdsDynamic.setId(Guid.newGuid()); vdsDynamic.setVmActive(random.nextInt()); vdsDynamic.setVmCount(random.nextInt()); vdsDynamic.setVmMigrating(random.nextInt()); vdsDynamic.setReservedMem(random.nextInt()); vdsDynamic.setGuestOverhead(random.nextInt()); vdsDynamic.setPreviousStatus(random.nextEnum(VDSStatus.class)); vdsDynamic.setSoftwareVersion(random.nextNumericString(5) + '.' + random.nextNumericString(5)); vdsDynamic.setVersionName(random.nextString(10)); vdsDynamic.setPendingVcpusCount(random.nextInt()); vdsDynamic.setPendingVmemSize(random.nextInt()); vdsDynamic.setNetConfigDirty(random.nextBoolean()); vdsDynamic.setTransparentHugePagesState(random.nextEnum(VdsTransparentHugePagesState.class)); vdsDynamic.setHardwareUUID(Guid.newGuid().toString()); vdsDynamic.setHardwareFamily(random.nextString(10)); vdsDynamic.setHardwareSerialNumber(random.nextString(10)); vdsDynamic.setHardwareVersion(random.nextString(10)); vdsDynamic.setHardwareProductName(random.nextString(10)); vdsDynamic.setHardwareManufacturer(random.nextString(10)); return vdsDynamic; } private static VdsStatistics randomVdsStatistics() { RandomUtils random = RandomUtils.instance(); VdsStatistics vdsStatistics = new VdsStatistics(); vdsStatistics.setCpuIdle(random.nextDouble()); vdsStatistics.setCpuLoad(random.nextDouble()); vdsStatistics.setCpuSys(random.nextDouble()); vdsStatistics.setCpuUser(random.nextDouble()); vdsStatistics.setMemAvailable(random.nextLong()); vdsStatistics.setMemFree(random.nextLong()); vdsStatistics.setMemShared(random.nextLong()); vdsStatistics.setUsageCpuPercent(random.nextInt()); vdsStatistics.setUsageMemPercent(random.nextInt()); vdsStatistics.setUsageNetworkPercent(random.nextInt()); vdsStatistics.setCpuOverCommitTimeStamp(new Date(random.nextLong())); return vdsStatistics; } private static Role randomRole() { RandomUtils random = RandomUtils.instance(); Role role = new Role(); role.setDescription(random.nextString(10)); role.setId(Guid.newGuid()); role.setName(random.nextString(10)); return role; } @Test public void serializeAndDesrializeEntity() throws Exception { String serializedEntity = new JsonObjectSerializer().serialize(entity); assertNotNull(serializedEntity); Serializable deserializedEntity = new JsonObjectDeserializer().deserialize(serializedEntity, entity.getClass()); assertNotNull(deserializedEntity); assertEquals(entity, deserializedEntity); } @Test public void serializeAndDeserializeExtMap() throws Exception { ExtMap data = new ExtMap(); data.put(Authn.AuthRecord.PRINCIPAL, "user1@BRQ-OPENLDAP.RHEV.LAB.ENG.BRQ.REDHAT.COM"); String json = serialize(data); assertTrue(json.length() > 0); ExtMap extMap = deserialize(json, ExtMap.class); assertNotNull(extMap); assertEquals(data, extMap); } @Test public void serializeAndDeserializeExtMapList() throws Exception { List<ExtMap> users = new ArrayList<>(); users.add(new ExtMap().mput(Authn.AuthRecord.PRINCIPAL, "user1@BRQ-OPENLDAP.RHEV.LAB.ENG.BRQ.REDHAT.COM")); users.add(new ExtMap().mput(Authn.AuthRecord.PRINCIPAL, "user2@BRQ-OPENLDAP.RHEV.LAB.ENG.BRQ.REDHAT.COM")); String json = serialize(users); assertTrue(json.length() > 0); List<ExtMap> deserializedUsers = deserialize(json, ArrayList.class); assertNotNull(deserializedUsers); assertEquals(users, deserializedUsers); } private String serialize(Object obj) throws IOException { ObjectMapper mapper = new ObjectMapper() .enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE); mapper.getSerializationConfig().addMixInAnnotations(ExtMap.class, JsonExtMapMixIn.class); return mapper.writeValueAsString(obj); } private <T> T deserialize(String json, Class<T> type) throws IOException { ObjectMapper mapper = new ObjectMapper().configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false) .enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE); mapper.getDeserializationConfig().addMixInAnnotations(ExtMap.class, JsonExtMapMixIn.class); return mapper.readValue(json, type); } /** * This class is used to test that a container class with a field with no concrete type information gets serialized * an deserializde normally. * * @param <ID> * The type of the id. */ @SuppressWarnings("serial") public static class IdContainerClass<ID extends Serializable> implements BusinessEntity<ID> { ID id; @SuppressWarnings("unused") private IdContainerClass() { } public IdContainerClass(ID id) { this.id = id; } /** * @return the id */ @Override public ID getId() { return id; } /** * @param id * the id to set */ @Override public void setId(ID id) { this.id = id; } @Override public int hashCode() { return Objects.hashCode(id); } @SuppressWarnings("rawtypes") @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof IdContainerClass)) { return false; } IdContainerClass other = (IdContainerClass) obj; return Objects.equals(id, other.id); } } }