/** * Copyright (C) 2015 Orange * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.francetelecom.clara.cloud.deployment.logical.service; import com.francetelecom.clara.cloud.commons.xstream.XStreamUtils; import com.francetelecom.clara.cloud.logicalmodel.*; import com.francetelecom.clara.cloud.logicalmodel.samplecatalog.SampleAppFactory; import com.thoughtworks.xstream.XStream; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.concurrent.Callable; import static org.junit.Assert.*; /** * Tests Xml-based LD cloning */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:/com/francetelecom/clara/cloud/services/application-context.xml"}) public class LogicalDeploymentClonerImplTest { private static Logger logger = LoggerFactory.getLogger(LogicalDeploymentClonerImplTest.class.getName()); @Autowired @Qualifier(value = "springooLogicalModelCatalog") SampleAppFactory sampleAppFactory; @Autowired LogicalDeploymentCloner cloner; @Autowired LogicalDeploymentRepository logicalDeploymentRepository; /** * Used for debugging and for assertion XML dump size as a way to validate equals */ private final XStream xStream = XStreamUtils.instanciateXstreamForHibernate(); @Test public void testTransientClone() throws Exception { testClone(false); } @Test @DirtiesContext @Ignore public void testPersistentClone() throws Exception { testClone(true); } private void testClone(final boolean persist) throws Exception { LogicalDeployment original = sampleAppFactory.populateLogicalDeployment(null); final String originalXmlDump = xStream.toXML(original); if (persist) { logicalDeploymentRepository.save(original); original = logicalDeploymentRepository.findOne(original.getId()); } final LogicalDeploymentCloner finalCloner = this.cloner; //syntaxic sugar for anonymous inner class. final LogicalDeployment finalOriginal = original; Callable<LogicalDeployment> cloneRunneable = new Callable<LogicalDeployment>() { @Override public LogicalDeployment call() throws Exception { LogicalDeployment ld; if (persist) { ld = logicalDeploymentRepository.findOne(finalOriginal.getId()); } else { ld = finalOriginal; } LogicalDeployment localClone = finalCloner.deepCopy(ld); if (persist) { logicalDeploymentRepository.save(localClone); } return localClone; } }; final LogicalDeployment finalClone = cloneRunneable.call(); // Check name unicity List<String> names = new ArrayList<String>(); names.add(finalClone.getName()); for (ProcessingNode node : finalClone.listProcessingNodes()) { if (names.contains(node.getName())) { fail("name is not unique: " + node.getName()); } names.add(node.getName()); assertTrue("name should be 36 characters long", node.getName().length() == 36); } for (LogicalService service : finalClone.listLogicalServices()) { if (names.contains(service.getName())) { fail("name is not unique: " + service.getName()); } assertTrue("name should be 36 characters long", service.getName().length() == 36); } Runnable assertEqualsWithinTransactionRunneable = new Runnable() { @Override public void run() { //Force XML dump to check objects can be properly iterated through, and to force their eager fetching LogicalDeployment reloadedOriginal; LogicalDeployment reloadedClone; if (persist) { reloadedOriginal = logicalDeploymentRepository.findOne(finalOriginal.getId()); reloadedClone = logicalDeploymentRepository.findOne(finalClone.getId()); } else { reloadedOriginal = finalOriginal; reloadedClone = finalClone; } String prefix = persist ? "Persisted " : "Transient"; logger.debug(prefix + "Original:\n" + xStream.toXML(reloadedOriginal)); String cloneXmlDump = xStream.toXML(reloadedClone); logger.debug(prefix + "Clone:\n" + cloneXmlDump); assertTrue("Expected XML dump to be as large as original (name prefix adds some chars)", cloneXmlDump.length() >= originalXmlDump.length()); assertEquals(reloadedOriginal, reloadedOriginal); assertEquals(reloadedClone, reloadedOriginal); assertNotSame(reloadedOriginal, reloadedClone); if (persist) { assertTrue("expected different db Ids, got:" + reloadedOriginal.getId(), reloadedOriginal.getId() != reloadedClone.getId()); } } }; assertEqualsWithinTransactionRunneable.run(); //Then make modifications to the clone and verify the original is not affected Set<LogicalWebGUIService> webGuis = finalClone.listLogicalServices(LogicalWebGUIService.class); for (LogicalWebGUIService webGui : webGuis) { webGui.setContextRoot(new ContextRoot("/")); } assertFalse("expected modified clone to differ from original", finalOriginal.equals(finalClone)); //verify the persisted original is not affected by modifications made to the clone Runnable assertNotEqualsWithinTransactionRunneable = new Runnable() { @Override public void run() { LogicalDeployment reloadedOriginal; LogicalDeployment reloadedClone; if (persist) { reloadedOriginal = logicalDeploymentRepository.findOne(finalOriginal.getId()); logicalDeploymentRepository.save(finalClone); //write to DB modifications made to the clone reloadedClone = logicalDeploymentRepository.findOne(finalClone.getId()); } else { reloadedOriginal = finalOriginal; reloadedClone = finalClone; } assertFalse("expected modified clone to differ from original", reloadedOriginal.equals(reloadedClone)); } }; assertNotEqualsWithinTransactionRunneable.run(); //direct execute outside of a transaction. } }