/*
* Copyright (c) 2014 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.db.server.upgrade.impl.callback;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import junit.framework.Assert;
import org.junit.BeforeClass;
import com.emc.storageos.db.client.URIUtil;
import com.emc.storageos.db.client.model.BlockMirror;
import com.emc.storageos.db.client.model.BlockObject;
import com.emc.storageos.db.client.model.BlockSnapshot;
import com.emc.storageos.db.client.model.Volume;
import com.emc.storageos.db.client.upgrade.BaseCustomMigrationCallback;
import com.emc.storageos.db.client.upgrade.callbacks.BlockObjectNormalizeWwnMigration;
import com.emc.storageos.db.server.DbsvcTestBase;
import com.emc.storageos.db.server.upgrade.DbSimpleMigrationTestBase;
/**
* Test proper normalizing of the BlockObject wwn field
*
* Here's the basic execution flow for the test case:
* - setup() runs, bringing up a "pre-migration" version
* of the database, using the DbSchemaScannerInterceptor
* you supply to hide your new field or column family
* when generating the "before" schema.
* - Your implementation of prepareData() is called, allowing
* you to use the internal _dbClient reference to create any
* needed pre-migration test data.
* - The database is then shutdown and restarted (without using
* the interceptor this time), so the full "after" schema
* is available.
* - The dbsvc detects the diffs in the schema and executes the
* migration callbacks as part of the startup process.
* - Your implementation of verifyResults() is called to
* allow you to confirm that the migration of your prepared
* data went as expected.
*
*/
public class BlockObjectNormalizeWwnMigrationTest extends DbSimpleMigrationTestBase {
private final int INSTANCES_TO_CREATE = 10;
private final int WWN_LENGTH = 32;
private Map<URI, String> blockObjectWwns = new HashMap<URI, String>();
@BeforeClass
public static void setup() throws IOException {
customMigrationCallbacks.put("2.1", new ArrayList<BaseCustomMigrationCallback>() {
{
add(new BlockObjectNormalizeWwnMigration());
}
});
DbsvcTestBase.setup();
}
@Override
protected String getSourceVersion() {
return "2.1";
}
@Override
protected String getTargetVersion() {
return "2.2";
}
@Override
protected void prepareData() throws Exception {
prepareBlockObjectData(Volume.class);
prepareBlockObjectData(BlockSnapshot.class);
prepareBlockObjectData(BlockMirror.class);
}
@Override
protected void verifyResults() throws Exception {
verifyBlockObjectData(Volume.class);
verifyBlockObjectData(BlockSnapshot.class);
verifyBlockObjectData(BlockMirror.class);
}
private void prepareBlockObjectData(Class<? extends BlockObject> clazz) throws Exception {
for (int i = 0; i < INSTANCES_TO_CREATE; i++) {
BlockObject blockObject = clazz.newInstance();
String lowerCaseWwn = generateLowerCaseWwn();
blockObject.setId(URIUtil.createId(clazz));
blockObjectWwns.put(blockObject.getId(), lowerCaseWwn);
blockObject.setWWN(lowerCaseWwn);
_dbClient.createObject(blockObject);
}
List<URI> keys = _dbClient.queryByType(clazz, false);
int count = 0;
for (@SuppressWarnings("unused")
URI ignore : keys) {
count++;
}
Assert.assertTrue("Expected " + INSTANCES_TO_CREATE + " prepared " + clazz.getSimpleName() + ", found only " + count,
count == INSTANCES_TO_CREATE);
}
private void verifyBlockObjectData(Class<? extends BlockObject> clazz) throws Exception {
List<URI> keys = _dbClient.queryByType(clazz, false);
int count = 0;
Iterator<? extends BlockObject> objs =
_dbClient.queryIterativeObjects(clazz, keys);
while (objs.hasNext()) {
BlockObject blockObject = objs.next();
count++;
Assert.assertTrue("Wwn should be upper case ", isUpperCase(blockObject.getWWN()));
Assert.assertTrue("Block object id should be in the map", blockObjectWwns.containsKey(blockObject.getId()));
Assert.assertEquals("Wwn should be upper case equivalent of lower case Wwn", blockObjectWwns.get(blockObject.getId())
.toUpperCase(), blockObject.getWWN());
}
Assert.assertTrue("We should still have " + INSTANCES_TO_CREATE + " " + clazz.getSimpleName() + " after migration, not " + count,
count == INSTANCES_TO_CREATE);
}
private String generateLowerCaseWwn() {
Random r = new Random();
StringBuffer sb = new StringBuffer();
while (sb.length() < WWN_LENGTH) {
sb.append(Integer.toHexString(r.nextInt()));
}
return sb.toString().substring(0, WWN_LENGTH).toLowerCase();
}
private boolean isUpperCase(String s) {
int size = s.length();
for (int i = 0; i < size; i++) {
if (!Character.isDigit(s.charAt(i))
&& !Character.isUpperCase(s.charAt(i))) {
return false;
}
}
return true;
}
}