/* * Copyright (c) 2015 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.smis; import java.net.URI; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Random; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.URIUtil; import com.emc.storageos.db.client.model.BlockObject; import com.emc.storageos.db.client.model.BlockSnapshot; import com.emc.storageos.db.client.model.StorageSystem; import com.emc.storageos.db.client.model.Volume; /* * Test class to test RefreshRequiredUpdateFunction.call() with simulated objects * It uses configuration files from dbclient, dbutils and coordinatorsvc */ public class RefreshRequiredUpdateFunctionTest { private static final Logger _logger = LoggerFactory .getLogger(RefreshRequiredUpdateFunctionTest.class); // number of storage systems in DB private static final int _storageSystemCount = 5; // number of block objects on each storage system, an even number. // volume and block snapshot each takes half // total number of block objects is _blockObjectCountPerSystem * // _storageSystemCount private static final int _blockObjectCountPerSystem = 10000; private DbClient _dbClient = null; // URIs of dummy block objects. Volume and BlockSnapshot are distributed // evenly private List<URI> _blockObjectURIs = new ArrayList<URI>(); // list of URIs used to create RefreshRequiredUpdateFunction instance private List<URI> _originalBlockObjectList = new ArrayList<URI>(); // Storage System URI used to create RefreshRequiredUpdateFunction instance private URI _storageSystemURI = null; @Before public void setup() { // get DB client ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext( "dbutils-conf.xml"); _dbClient = (DbClient) ctx.getBean("dbclient"); _dbClient.start(); } @After public void cleanup() { if (_dbClient != null) { _dbClient.stop(); } } @Test /* * Test RefreshRequiredUpdateFunction.call method */ public void testRefresh() { // populate DB with dummy Volume/BlockSnapshot createBlockObjects(); _originalBlockObjectList.add(_blockObjectURIs.get(0)); _originalBlockObjectList.add(_blockObjectURIs.get(1)); RefreshRequiredUpdateFunction refreshFunction = new RefreshRequiredUpdateFunction( _storageSystemURI, _originalBlockObjectList, _dbClient); long start = System.currentTimeMillis(); refreshFunction.call(); _logger.info("Refresh finished within (s) " + ((double) System.currentTimeMillis() - start) / 1000); // verify block objects and clean up DB verifyAndDeleteBlockObjects(); _logger.info("testRefresh finished"); } /* * Create Volume/BlockSnapshot for all Storage Systems */ private void createBlockObjects() { for (int i = 0; i < _storageSystemCount; i++) { URI storageSystemURI = URIUtil.createId(StorageSystem.class); if (i == 0) { // use the first storage system to create // RefreshRequiredUpdateFunction _storageSystemURI = storageSystemURI; } createBlockObjects(_blockObjectCountPerSystem, storageSystemURI); } } /* * Create Volume/BlockSnapshot for one Storage Systems * * @param numOfObject number of block objects to be created * * @param storageSystemURI URI of Storage Controller */ private void createBlockObjects(int numOfObject, URI storageSystemURI) { List<BlockObject> blockObjects = new ArrayList<BlockObject>(numOfObject); Random random = new Random(); boolean isVolume = true; for (int i = 0; i < numOfObject; i++) { BlockObject blockObject = createBlockObject(isVolume ? Volume.class : BlockSnapshot.class); _blockObjectURIs.add(blockObject.getId()); blockObject.setStorageController(storageSystemURI); // set the refreshRequired flag randomly blockObject.setRefreshRequired(random.nextBoolean()); blockObjects.add(blockObject); // create Volume and BlockSnapshot alternatively isVolume = !isVolume; } _dbClient.createObject(blockObjects); } /* * Create one block object * * @param clazz type of block object to be created * * @return block object of given type, not persisted yet */ private BlockObject createBlockObject(Class<? extends BlockObject> clazz) { BlockObject blockObject = null; try { blockObject = clazz.newInstance(); URI blockObjectURI = URIUtil.createId(clazz); blockObject.setId(blockObjectURI); // set the object active blockObject.setInactive(false); blockObject.setLabel("Dummy Object"); blockObject.setNativeGuid("SYMMETRIX+000123456789+VOLUME+00000"); } catch (InstantiationException e) { _logger.error("InstantiationException: " + e.getMessage()); } catch (IllegalAccessException e) { _logger.error("IllegalAccessException: " + e.getMessage()); } Assert.assertNotNull(blockObject); return blockObject; } /* * Verify all objects, and delete them from DB */ private void verifyAndDeleteBlockObjects() { List<URI> volumeURIs = new ArrayList<URI>(); List<URI> blockSnapshotURIs = new ArrayList<URI>(); for (URI uri : _blockObjectURIs) { if (URIUtil.isType(uri, Volume.class)) { volumeURIs.add(uri); } else { blockSnapshotURIs.add(uri); } } // verify and delete Volume and BlockSnapshot verifyAndDeleteBlockObjects(Volume.class, volumeURIs); verifyAndDeleteBlockObjects(BlockSnapshot.class, blockSnapshotURIs); } /* * Verify a list of block objects of given type */ private <T extends BlockObject> void verifyAndDeleteBlockObjects( Class<T> clazz, List<URI> blockObjectURIs) { // get all objects in the list Iterator<T> iBlockObjects = _dbClient.queryIterativeObjects(clazz, blockObjectURIs); List<T> blockObjects = new ArrayList<T>(); while (iBlockObjects.hasNext()) { T blockObject = iBlockObjects.next(); // check if it should be refreshed if (this._originalBlockObjectList.contains(blockObject.getId()) || _storageSystemURI.equals(blockObject .getStorageController())) { // verify it has been refreshed Assert.assertFalse(blockObject.getRefreshRequired()); } // add to list to be deleted blockObjects.add(blockObject); } // delete all objects in the list _dbClient.removeObject(blockObjects .toArray(new BlockObject[blockObjects.size()])); blockObjectURIs.clear(); } }