/* * Copyright (c) 2014 EMC Corporation * All Rights Reserved */ package com.emc.storageos.db.modelclient; import java.io.File; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.coordinator.client.model.Constants; import com.emc.storageos.coordinator.client.model.DbVersionInfo; import com.emc.storageos.coordinator.client.model.MigrationStatus; import com.emc.storageos.coordinator.client.service.DrUtil; import com.emc.storageos.coordinator.common.Configuration; import com.emc.storageos.coordinator.common.impl.ConfigurationImpl; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.DbModelClient; import com.emc.storageos.db.client.URIUtil; import com.emc.storageos.db.client.impl.DbClientContext; import com.emc.storageos.db.client.impl.DbModelClientImpl; import com.emc.storageos.db.client.model.DataObject; import com.emc.storageos.db.client.model.StringSet; import com.emc.storageos.db.common.DataObjectScanner; import com.emc.storageos.db.common.VdcUtil; import com.emc.storageos.db.modelclient.model.BlockMirror; import com.emc.storageos.db.modelclient.model.BlockObject; import com.emc.storageos.db.modelclient.model.BlockSnapshot; import com.emc.storageos.db.modelclient.model.ClassAManyToMany; import com.emc.storageos.db.modelclient.model.ClassAOneToMany; import com.emc.storageos.db.modelclient.model.ClassAOneToOne; import com.emc.storageos.db.modelclient.model.ClassBManyToMany; import com.emc.storageos.db.modelclient.model.ClassBOneToMany; import com.emc.storageos.db.modelclient.model.ClassBOneToOne; import com.emc.storageos.db.modelclient.model.ExportGroup; import com.emc.storageos.db.modelclient.model.ExportMask; import com.emc.storageos.db.modelclient.model.StorageDevice; import com.emc.storageos.db.modelclient.model.StoragePool; import com.emc.storageos.db.modelclient.model.StorageSystem; import com.emc.storageos.db.modelclient.model.VirtualArray; import com.emc.storageos.db.modelclient.model.Volume; import com.emc.storageos.db.server.DbClientTest.DbClientImplUnitTester; import com.emc.storageos.db.server.DbsvcTestBase; /** * @author cgarber * */ public class LazyLoadTests extends DbsvcTestBase { private static final Logger _log = LoggerFactory.getLogger(LazyLoadTests.class); private DbModelClient modelClient; private DbClient _dbClient; @BeforeClass public static void setup() throws IOException { sourceVersion = new DbVersionInfo(); sourceVersion.setSchemaVersion("1.1"); _dataDir = new File(dataDir); if (_dataDir.exists() && _dataDir.isDirectory()) { cleanDirectory(_dataDir); } _dataDir.mkdir(); DataObjectScanner scanner = new DataObjectScanner(); scanner.setPackages("com.emc.storageos.db.modelclient.model"); scanner.init(); // setting migration status to failed is a workaround for getting into // an endless loop of trying to run migration; if it's set to failed, we // simply by-pass migration; the other side affect is we don't start any // of the dbsvc background tasks, but we don't need them for this test setMigrationStatus(MigrationStatus.FAILED); startDb(sourceVersion.getSchemaVersion(), sourceVersion.getSchemaVersion(), null, scanner, false); } @Before public void setupTest() { DbClientImplUnitTester dbClient = new DbClientImplUnitTester(); dbClient.setCoordinatorClient(_coordinator); dbClient.setDbVersionInfo(sourceVersion); dbClient.setBypassMigrationLock(true); _encryptionProvider.setCoordinator(_coordinator); dbClient.setEncryptionProvider(_encryptionProvider); DbClientContext localCtx = new DbClientContext(); localCtx.setClusterName("Test"); localCtx.setKeyspaceName("Test"); dbClient.setLocalContext(localCtx); VdcUtil.setDbClient(dbClient); dbClient.setBypassMigrationLock(false); dbClient.setDrUtil(new DrUtil(_coordinator)); dbClient.start(); _dbClient = dbClient; modelClient = new DbModelClientImpl(_dbClient); } private static void setMigrationStatus(MigrationStatus status) { String dbConfigPath = _coordinator.getVersionedDbConfigPath("dbsvc", "1.1"); Configuration config = _coordinator.queryConfiguration(dbConfigPath, Constants.GLOBAL_ID); if (config == null) { ConfigurationImpl cfg = new ConfigurationImpl(); cfg.setKind(dbConfigPath); cfg.setId(Constants.GLOBAL_ID); config = cfg; } config.setConfig(Constants.MIGRATION_STATUS, status.name()); _coordinator.persistServiceConfiguration(config); } @After public void teardown() { if (_dbClient instanceof DbClientImplUnitTester) { ((DbClientImplUnitTester) _dbClient).removeAll(); } } private List<StorageSystem> createStorageSystems(int count, String labelPrefix, URI varrayId) { List<StorageSystem> systems = new ArrayList<StorageSystem>(count); for (int i = 0; i < count; i++) { StorageSystem system = new StorageSystem(); system.setId(URIUtil.createId(StorageSystem.class)); system.setLabel(labelPrefix + i); system.setVirtualArray(varrayId); modelClient.create(system); systems.add(system); } return systems; } private List<ExportGroup> createExportGroups(int count, Collection<ExportMask> ems, Collection<BlockSnapshot> snapshots) { List<ExportGroup> egs = new ArrayList<ExportGroup>(count); for (int i = 0; i < count; i++) { ExportGroup eg = new ExportGroup(); eg.setId(URIUtil.createId(ExportGroup.class)); String label = String.format("%1$d :/#$#@$\\: Test Label", i); eg.setLabel(label); if (ems != null) { StringSet emStrSet = new StringSet(); StringSet emLabelStrSet = new StringSet(); for (ExportMask mask : ems) { emStrSet.add(mask.getId().toString()); emLabelStrSet.add(mask.getLabel()); } eg.setExportMasks(emStrSet); eg.setExportMaskLabels(emLabelStrSet); } if (snapshots != null) { StringSet snapshotStrSet = new StringSet(); for (BlockSnapshot snapshot : snapshots) { snapshotStrSet.add(snapshot.getId().toString()); } eg.setSnapshots(snapshotStrSet); } modelClient.create(eg); egs.add(eg); } return egs; } private <T extends DataObject> List<T> createDbObject(Class<T> clazz, int count) throws InstantiationException, IllegalAccessException { List<T> ems = new ArrayList<T>(count); for (int i = 0; i < count; i++) { T obj = clazz.newInstance(); obj.setId(URIUtil.createId(clazz)); String label = String.format("%1$d :/#$#@$\\: Test Label", i); obj.setLabel(label); modelClient.create(obj); ems.add(obj); } return ems; } @Test public void testBasicQuery() { try { int numVirtualArrays = 1; int numStorageSystems = 5; int numExportGroups = 1; int numExportMasks = 5; int numSnapshots = 3; URI vArrayId = createDbObject(VirtualArray.class, numVirtualArrays).iterator().next().getId(); List<StorageSystem> systems = createStorageSystems(numStorageSystems, "system", vArrayId); // storageSystems in VirtualArray is mapped by a VirtualArray URI field in StorageSystems VirtualArray varray = modelClient.find(VirtualArray.class, vArrayId); List<StorageSystem> lazyLoadedSystems = varray.getStorageSystems(); Assert.assertNotNull(lazyLoadedSystems); Assert.assertEquals(systems.size(), lazyLoadedSystems.size()); // virtual array in storage system is mapped by a single URI (this tests lazy loading a single object as // opposed to a list) for (StorageSystem system : lazyLoadedSystems) { Assert.assertNotNull(system.getVArray()); Assert.assertEquals(varray.getId(), system.getVArray().getId()); } // export masks in export group is mapped by a stringset in export group // exportMaskSet is implemented as a ArrayList URI groupId = createExportGroups(numExportGroups, createDbObject(ExportMask.class, numExportMasks), createDbObject(BlockSnapshot.class, numSnapshots)).iterator().next().getId(); Iterator<ExportMask> allMasks = modelClient.findAll(ExportMask.class); int numFound = 0; while (allMasks.hasNext()) { numFound++; allMasks.next(); } Assert.assertEquals(numExportMasks, numFound); ExportGroup group = modelClient.find(ExportGroup.class, groupId); List<ExportMask> masks = group.getExportMaskSet(); Assert.assertNotNull(masks); Assert.assertEquals(numExportMasks, masks.size()); // snapshots in export group is mapped by a stringset in export group // snapshotSet is implemented as a HashSet Assert.assertNotNull(group.getSnapshotSet()); Assert.assertEquals(numSnapshots, group.getSnapshotSet().size()); } catch (Exception e) { _log.error(e.getMessage(), e); Assert.fail(e.getMessage()); } } @Test public void multiLevelSingleObjectRelationships() { try { Volume volume = createDbObject(Volume.class, 1).iterator().next(); StoragePool pool = createDbObject(StoragePool.class, 1).iterator().next(); StorageSystem device = createDbObject(StorageSystem.class, 1).iterator().next(); VirtualArray vArray = createDbObject(VirtualArray.class, 1).iterator().next(); volume.setPool(pool.getId()); modelClient.update(volume); pool.setStorageDevice(device.getId()); modelClient.update(pool); device.setVirtualArray(vArray.getId()); modelClient.update(device); Volume queriedVol = modelClient.find(Volume.class, volume.getId()); Assert.assertEquals(volume.getId(), queriedVol.getId()); Assert.assertEquals(pool.getId(), queriedVol.getStoragePool().getId()); Assert.assertEquals(device.getId(), queriedVol.getStoragePool().getStorageDeviceObj().getId()); Assert.assertEquals(vArray.getId(), queriedVol.getStoragePool().getStorageDeviceObj().getVArray().getId()); } catch (Exception e) { _log.error(e.getMessage(), e); Assert.fail(e.getMessage()); } } @Test @Ignore("not supported") public void testReferenceByLabel() { try { int numExportGroups = 1; int numExportMasks = 5; int numSnapshots = 3; URI groupId = createExportGroups(numExportGroups, createDbObject(ExportMask.class, numExportMasks), createDbObject(BlockSnapshot.class, numSnapshots)).iterator().next().getId(); ExportGroup group = modelClient.find(ExportGroup.class, groupId); List<ExportMask> masks = group.getExportMasksFromLabels(); Assert.assertNotNull(masks); Assert.assertEquals(numExportMasks, masks.size()); } catch (Exception e) { _log.error(e.getMessage(), e); Assert.fail(e.getMessage()); } } @Test public void testModifyList() { // demonstrates that if we modify the lazy loaded list, the stringset reflects the change try { int numExportGroups = 1; int numExportMasks = 5; int numExportMasksAdded = 1; int numSnapshots = 3; int numSnapshotsAdded = 5; URI groupId = createExportGroups(numExportGroups, createDbObject(ExportMask.class, numExportMasks), createDbObject(BlockSnapshot.class, numSnapshots)).iterator().next().getId(); ExportGroup group = modelClient.find(ExportGroup.class, groupId); Assert.assertEquals(numExportMasks, group.getExportMaskSet().size()); // add some new export masks to the lazy loaded list List<ExportMask> masks = createDbObject(ExportMask.class, numExportMasksAdded); for (ExportMask mask : masks) { group.addExportMask(mask); } // test before we persist Assert.assertEquals(numExportMasks + numExportMasksAdded, group.getExportMasks().size()); modelClient.update(group); // test again after we persist (the list should not get loaded again) Assert.assertEquals(numExportMasks + numExportMasksAdded, group.getExportMasks().size()); Assert.assertEquals(numSnapshots, group.getSnapshotSet().size()); // add an entirely new snapshot list List<BlockSnapshot> snapshotsToAdd = createDbObject(BlockSnapshot.class, numSnapshotsAdded); Set<BlockSnapshot> snapshots = new HashSet<BlockSnapshot>(); snapshots.addAll(group.getSnapshotSet()); for (BlockSnapshot snapshot : snapshotsToAdd) { snapshots.add(snapshot); } group.setSnapshotSet(snapshots); // test before we persist Assert.assertEquals(numSnapshots + numSnapshotsAdded, group.getSnapshots().size()); Assert.assertEquals(numSnapshots + numSnapshotsAdded, group.getSnapshotSet().size()); modelClient.update(group); // test again after we persist (the list should not get loaded again) Assert.assertEquals(numSnapshots + numSnapshotsAdded, group.getSnapshots().size()); Assert.assertEquals(numSnapshots + numSnapshotsAdded, group.getSnapshotSet().size()); // now test removing things from lists BlockSnapshot snapshotToRemove = group.getSnapshotSet().iterator().next(); group.getSnapshotSet().remove(snapshotToRemove); Assert.assertEquals(numSnapshots + numSnapshotsAdded - 1, group.getSnapshots().size()); Assert.assertEquals(numSnapshots + numSnapshotsAdded - 1, group.getSnapshotSet().size()); ExportMask maskToRemove = group.getExportMaskSet().iterator().next(); group.removeExportMask(maskToRemove); Assert.assertEquals(numExportMasks + numExportMasksAdded - 1, group.getExportMasks().size()); Assert.assertEquals(numExportMasks + numExportMasksAdded - 1, group.getExportMaskSet().size()); modelClient.update(group); Assert.assertEquals(numExportMasks + numExportMasksAdded - 1, group.getExportMasks().size()); Assert.assertEquals(numExportMasks + numExportMasksAdded - 1, group.getExportMaskSet().size()); Assert.assertEquals(numSnapshots + numSnapshotsAdded - 1, group.getSnapshots().size()); Assert.assertEquals(numSnapshots + numSnapshotsAdded - 1, group.getSnapshotSet().size()); // use iterator to remove an item // TODO this is a gotcha: can't use iterator to manipulate the list // Iterator<ExportMask> maskItr = group.getExportMaskSet().iterator(); // ExportMask maskToRemove2 = maskItr.next(); // maskItr.remove(); // Assert.assertEquals(numExportMasks+numExportMasksAdded-2, group.getExportMasks().size()); // Assert.assertEquals(numExportMasks+numExportMasksAdded-2, group.getExportMaskSet().size()); // // modelClient.update(group); // Assert.assertEquals(numExportMasks+numExportMasksAdded-2, group.getExportMasks().size()); // Assert.assertEquals(numExportMasks+numExportMasksAdded-2, group.getExportMaskSet().size()); // add a new ExportGroup with export masks added to the lazy loaded list ExportGroup group2 = new ExportGroup(); group2.setId(URIUtil.createId(ExportGroup.class)); group2.setLabel("group2"); List<ExportMask> exportMasks2 = createDbObject(ExportMask.class, 3); for (ExportMask mask : exportMasks2) { group2.addExportMask(mask); } modelClient.create(group2); Assert.assertEquals(3, group2.getExportMasks().size()); Assert.assertEquals(3, group2.getExportMaskSet().size()); // add a new ExportGroup with export masks added to the lazy loaded list reseting the whole list ExportGroup group3 = new ExportGroup(); group3.setId(URIUtil.createId(ExportGroup.class)); group3.setLabel("group3"); List<ExportMask> exportMasks3 = createDbObject(ExportMask.class, 3); group3.setExportMaskSet(exportMasks3); modelClient.create(group3); Assert.assertEquals(3, group3.getExportMasks().size()); Assert.assertEquals(3, group3.getExportMaskSet().size()); } catch (Exception e) { _log.error(e.getMessage(), e); Assert.fail(e.getMessage()); } } @Test public void testModifyStringSet() { // demonstrates that if we modify a stringset, the associated lazy loaded list reflects the change try { int numExportGroups = 1; int numExportMasks = 5; int numExportMasksAdded = 1; int numSnapshots = 3; int numSnapshotsAdded = 5; URI groupId = createExportGroups(numExportGroups, createDbObject(ExportMask.class, numExportMasks), createDbObject(BlockSnapshot.class, numSnapshots)).iterator().next().getId(); ExportGroup group = modelClient.find(ExportGroup.class, groupId); Assert.assertEquals(numExportMasks, group.getExportMaskSet().size()); // add some more export masks to the stringset List<ExportMask> masks = createDbObject(ExportMask.class, numExportMasksAdded); for (ExportMask mask : masks) { group.addExportMask(mask.getId()); } // test before we persist Assert.assertEquals(numExportMasks + numExportMasksAdded, group.getExportMaskSet().size()); modelClient.update(group); // test again after we persist (the list should not get loaded again) Assert.assertEquals(numExportMasks + numExportMasksAdded, group.getExportMaskSet().size()); List<BlockSnapshot> snapshotsToAdd = createDbObject(BlockSnapshot.class, numSnapshotsAdded); for (BlockSnapshot snapshot : snapshotsToAdd) { group.getSnapshots().add(snapshot.getId().toString()); } // test before we persist Assert.assertEquals(numSnapshots + numSnapshotsAdded, group.getSnapshotSet().size()); modelClient.update(group); // test again after we persist (the list should not get loaded again) Assert.assertEquals(numSnapshots + numSnapshotsAdded, group.getSnapshotSet().size()); // now test removing things from stringsets group.removeExportMask(masks.iterator().next().getId()); group.getSnapshots().remove(snapshotsToAdd.iterator().next().getId().toString()); Assert.assertEquals(numExportMasks + numExportMasksAdded - 1, group.getExportMaskSet().size()); Assert.assertEquals(numSnapshots + numSnapshotsAdded - 1, group.getSnapshotSet().size()); modelClient.update(group); Assert.assertEquals(numExportMasks + numExportMasksAdded - 1, group.getExportMaskSet().size()); Assert.assertEquals(numSnapshots + numSnapshotsAdded - 1, group.getSnapshotSet().size()); } catch (Exception e) { _log.error(e.getMessage(), e); Assert.fail(e.getMessage()); } } // @Ignore("not working") @Test public void testModifyDataObjectField() { ClassAOneToOne aInst = new ClassAOneToOne(); aInst.setId(URIUtil.createId(ClassAOneToOne.class)); aInst.setLabel("Instance of ClassA"); ClassBOneToOne bInst = new ClassBOneToOne(); bInst.setId(URIUtil.createId(ClassBOneToOne.class)); bInst.setLabel("Instance of ClassB"); aInst.setBinstance(bInst); modelClient.create(bInst); modelClient.create(aInst); ClassAOneToOne qAinst = modelClient.find(ClassAOneToOne.class, aInst.getId()); Assert.assertNotNull(aInst.getBid()); Assert.assertEquals(bInst.getId(), aInst.getBid()); ClassBOneToOne bInst2 = new ClassBOneToOne(); bInst2.setId(URIUtil.createId(ClassBOneToOne.class)); bInst2.setLabel("Instance 2 of ClassB"); modelClient.create(bInst2); qAinst.setBinstance(bInst2); Assert.assertNotNull(qAinst.getBid()); Assert.assertEquals(bInst2.getId(), qAinst.getBid()); modelClient.update(qAinst); ClassAOneToOne qAinst2 = modelClient.find(ClassAOneToOne.class, aInst.getId()); Assert.assertNotNull(qAinst2.getBinstance()); Assert.assertEquals(bInst2.getId(), qAinst2.getBinstance().getId()); } @Test public void testModifyURIField() { ClassAOneToOne aInst = new ClassAOneToOne(); aInst.setId(URIUtil.createId(ClassAOneToOne.class)); aInst.setLabel("Instance of ClassA"); ClassBOneToOne bInst = new ClassBOneToOne(); bInst.setId(URIUtil.createId(ClassBOneToOne.class)); bInst.setLabel("Instance of ClassB"); aInst.setBinstance(bInst); modelClient.create(bInst); modelClient.create(aInst); ClassAOneToOne qAinst = modelClient.find(ClassAOneToOne.class, aInst.getId()); Assert.assertNotNull(qAinst.getBid()); Assert.assertEquals(bInst.getId(), qAinst.getBid()); Assert.assertEquals(bInst.getId(), qAinst.getBinstance().getId()); ClassBOneToOne bInst2 = new ClassBOneToOne(); bInst2.setId(URIUtil.createId(ClassBOneToOne.class)); bInst2.setLabel("Instance 2 of ClassB"); modelClient.create(bInst2); qAinst.setBid(bInst2.getId()); Assert.assertNotNull(qAinst.getBinstance()); Assert.assertEquals(bInst2.getId(), qAinst.getBinstance().getId()); modelClient.update(qAinst); ClassAOneToOne qAinst2 = modelClient.find(ClassAOneToOne.class, aInst.getId()); Assert.assertNotNull(qAinst2.getBinstance()); Assert.assertEquals(bInst2.getId(), qAinst2.getBinstance().getId()); } @Test public void testConvertBetweenListAndIterator() { try { URI groupId = createExportGroups(1, createDbObject(ExportMask.class, 5), null).iterator().next().getId(); ExportGroup group = modelClient.find(ExportGroup.class, groupId); // this will load iterator only Assert.assertTrue(group.getExportMaskSet().iterator().hasNext()); // this will reload with a list Assert.assertEquals(5, group.getExportMaskSet().size()); } catch (Exception e) { _log.error(e.getMessage(), e); Assert.fail(e.getMessage()); } } @Test public void testWithNewlyCreatedObj() { try { ExportGroup group = createExportGroups(1, createDbObject(ExportMask.class, 5), null).iterator().next(); Assert.assertEquals(5, group.getExportMaskSet().size()); group = modelClient.find(ExportGroup.class, group.getId()); Assert.assertEquals(5, group.getExportMaskSet().size()); } catch (Exception e) { _log.error(e.getMessage(), e); Assert.fail(e.getMessage()); } } @Test @Ignore("Unsupported") public void testCascadingInsert() { try { VirtualArray vArray = new VirtualArray(); vArray.setId(URIUtil.createId(VirtualArray.class)); vArray.setLabel("varray1"); StorageSystem ss = new StorageSystem(); ss.setId(URIUtil.createId(StorageSystem.class)); ss.setLabel("storagesys1"); // TODO : URI should be set automatically when we call setVArray() ss.setVirtualArray(vArray.getId()); ss.setVArray(vArray); modelClient.create(ss); VirtualArray qv = modelClient.find(VirtualArray.class, vArray.getId()); Assert.assertNotNull(qv.getStorageSystems()); Assert.assertEquals(1, qv.getStorageSystems().size()); StorageSystem qss = modelClient.find(StorageSystem.class, ss.getId()); Assert.assertNotNull(qss.getVArray()); Assert.assertEquals(vArray.getId(), qss.getVArray().getId()); } catch (Exception e) { _log.error(e.getMessage(), e); Assert.fail(e.getMessage()); } } @Test public void joinerTestMatchTest() { try { createExportGroups(1, createDbObject(ExportMask.class, 5), null).iterator().next().getId(); Iterator<ExportMask> masks = modelClient.findAll(ExportMask.class); int count = 0; while (masks.hasNext()) { ExportMask mask = masks.next(); mask.setIndexedField(count < 3 ? "test-value-1" : "test-value-2"); mask.setUnIndexedField(count < 3 ? "test-value-1" : "test-value-2"); modelClient.update(mask); count++; } List<ExportMask> qMasks = modelClient.join(ExportMask.class, "masks").match("indexedField", "test-value-2") .go().list("masks"); Assert.assertEquals(2, qMasks.size()); List<ExportMask> qMasks2 = modelClient.join(ExportMask.class, "masks").match("unIndexedField", "test-value-1") .go().list("masks"); Assert.assertEquals(3, qMasks2.size()); List<ExportMask> qMasks3 = modelClient.join(ExportGroup.class, "groups") .join("groups", "exportMasks", ExportMask.class, "masks").match("indexedField", "test-value-2") .go().list("masks"); Assert.assertEquals(2, qMasks3.size()); List<ExportMask> qMasks4 = modelClient.join(ExportGroup.class, "groups") .join("groups", "exportMasks", ExportMask.class, "masks").match("unIndexedField", "test-value-1") .go().list("masks"); Assert.assertEquals(3, qMasks4.size()); } catch (InstantiationException | IllegalAccessException e) { // TODO Auto-generated catch block _log.error(e.getMessage(), e); } } @Test public void joinerTest() { try { URI groupId = createExportGroups(1, createDbObject(ExportMask.class, 5), null).iterator().next().getId(); ExportGroup group = modelClient.find(ExportGroup.class, groupId); Iterator<ExportMask> masks = modelClient.findAll(ExportMask.class); // URI device = URIUtil.createId(StorageDevice.class); List<StorageDevice> sdList = createDbObject(StorageDevice.class, 4); StorageDevice sd1 = sdList.get(0); StorageDevice sd2 = sdList.get(1); int count = 0; while (masks.hasNext()) { ExportMask mask = masks.next(); mask.setStorageDevice(count < 3 ? sd1.getId() : sd2.getId()); modelClient.update(mask); count++; } List<ExportMask> masks1 = modelClient.join(ExportGroup.class, "one") .join("one", "exportMasks", ExportMask.class, "two") .go().list("two"); Assert.assertEquals(5, masks1.size()); List<StorageDevice> devices1 = modelClient.join(ExportMask.class, "two") .join("two", "storageDevice", StorageDevice.class, "three") .go().list("three"); Assert.assertEquals(2, devices1.size()); List<StorageDevice> devices = modelClient.join(ExportGroup.class, "one") .join("one", "exportMasks", ExportMask.class, "two") .join("two", "storageDevice", StorageDevice.class, "three") .go().list("three"); Assert.assertEquals(2, devices.size()); List<ExportMask> masksWithSdId1 = modelClient.join(StorageDevice.class, "one") .match("label", sd1.getLabel()) .join("one", ExportMask.class, "two", "storageDevice") .go().list("two"); Assert.assertEquals(3, masksWithSdId1.size()); List<ExportMask> masksWithSdId2 = modelClient.join(StorageDevice.class, "one") .match("label", sd2.getLabel()) .join("one", ExportMask.class, "two", "storageDevice") .go().list("two"); Assert.assertEquals(2, masksWithSdId2.size()); List<ExportMask> masks3 = modelClient.join(ExportMask.class, "one").match("storageDevice", sd1.getId()) .go().list("one"); Assert.assertEquals(3, masks3.size()); } catch (Exception e) { _log.error(e.getMessage(), e); Assert.fail(e.getMessage()); } } @Test public void ModelClientTest() { try { URI vArrayId = createDbObject(VirtualArray.class, 1).iterator().next().getId(); List<StorageSystem> systems = createStorageSystems(5, "system", vArrayId); Iterator<StorageSystem> queried = modelClient.find(StorageSystem.class, "varray", vArrayId); int num = 0; while (queried.hasNext()) { num++; queried.next(); } Assert.assertEquals(systems.size(), num); queried = modelClient.find(StorageSystem.class, "varray", vArrayId.toString()); num = 0; while (queried.hasNext()) { num++; queried.next(); } Assert.assertEquals(systems.size(), num); StringSet stringset = new StringSet(); stringset.add(vArrayId.toString()); stringset.add(URIUtil.createId(VirtualArray.class).toString()); queried = modelClient.find(StorageSystem.class, "varray", stringset); num = 0; while (queried.hasNext()) { num++; queried.next(); } Assert.assertEquals(systems.size(), num); List<ExportMask> masks = createDbObject(ExportMask.class, 1); List<ExportGroup> groups = createExportGroups(5, masks, null); Iterator<ExportGroup> queriedGroups = modelClient.find(ExportGroup.class, "exportMasks", masks.iterator().next().getId()); num = 0; while (queriedGroups.hasNext()) { num++; queriedGroups.next(); } Assert.assertEquals(groups.size(), num); } catch (Exception e) { _log.error(e.getMessage(), e); Assert.fail(e.getMessage()); } } @Test @Ignore("not supported") public void joinerTest2() { try { URI groupId = createExportGroups(1, createDbObject(ExportMask.class, 5), null).iterator().next().getId(); ExportGroup group = modelClient.find(ExportGroup.class, groupId); List<ExportMask> masks = modelClient.join(ExportGroup.class, "one", group.getId()) .join("one", "exportMasksByLabel", ExportMask.class, "two").go().list("two"); Assert.assertEquals(5, masks.size()); } catch (Exception e) { _log.error(e.getMessage(), e); Assert.fail(e.getMessage()); } } @Test public void testAddAllFromLLList() { try { URI groupId = createExportGroups(1, createDbObject(ExportMask.class, 3), createDbObject(BlockSnapshot.class, 3)).iterator() .next().getId(); Set<BlockSnapshot> snapshots = new HashSet<BlockSnapshot>(); ExportGroup group = modelClient.find(ExportGroup.class, groupId); snapshots.addAll(group.getSnapshotSet()); Assert.assertEquals(3, snapshots.size()); } catch (Exception e) { _log.error(e.getMessage(), e); Assert.fail(e.getMessage()); } } @Test public void testOneToOne() { ClassAOneToOne aInst = new ClassAOneToOne(); aInst.setId(URIUtil.createId(ClassAOneToOne.class)); aInst.setLabel("Instance of ClassA"); ClassBOneToOne bInst = new ClassBOneToOne(); bInst.setId(URIUtil.createId(ClassBOneToOne.class)); bInst.setLabel("Instance of ClassB"); aInst.setBinstance(bInst); modelClient.create(aInst); modelClient.create(bInst); ClassAOneToOne qAinst = modelClient.find(ClassAOneToOne.class, aInst.getId()); ClassBOneToOne lazyLoadedBinst = qAinst.getBinstance(); Assert.assertNotNull(lazyLoadedBinst); Assert.assertEquals(bInst.getId(), lazyLoadedBinst.getId()); ClassBOneToOne qBinst = modelClient.find(ClassBOneToOne.class, bInst.getId()); ClassAOneToOne lazyLoadedAinst = qBinst.getAinstance(); Assert.assertNotNull(lazyLoadedAinst); Assert.assertEquals(aInst.getId(), lazyLoadedAinst.getId()); } @Test public void testOneToMany() { ClassAOneToMany aInst = new ClassAOneToMany(); aInst.setId(URIUtil.createId(ClassAOneToMany.class)); aInst.setLabel("Instance of ClassA"); modelClient.create(aInst); ClassBOneToMany bInst1 = new ClassBOneToMany(); bInst1.setId(URIUtil.createId(ClassBOneToMany.class)); bInst1.setLabel("Instance (1) of ClassB"); modelClient.create(bInst1); ClassBOneToMany bInst2 = new ClassBOneToMany(); bInst2.setId(URIUtil.createId(ClassBOneToMany.class)); bInst2.setLabel("Instance (2) of ClassB"); modelClient.create(bInst2); StringSet bIds = new StringSet(); bIds.add(bInst1.getId().toString()); bIds.add(bInst2.getId().toString()); aInst.setBids(bIds); // aInst.addB(bInst1); // aInst.addB(bInst2); modelClient.update(aInst); ClassAOneToMany qAinst = modelClient.find(ClassAOneToMany.class, aInst.getId()); List<ClassBOneToMany> lazyLoadedBs = qAinst.getBinstances(); Assert.assertNotNull(lazyLoadedBs); Assert.assertEquals(2, lazyLoadedBs.size()); ClassBOneToMany qBinst = modelClient.find(ClassBOneToMany.class, lazyLoadedBs.iterator().next().getId()); ClassAOneToMany lazyLoadedAinst = qBinst.getAinstance(); Assert.assertNotNull(lazyLoadedAinst); Assert.assertEquals(aInst.getId(), lazyLoadedAinst.getId()); } @Test public void testManyToMany() { ClassBManyToMany bInst1 = new ClassBManyToMany(); bInst1.setId(URIUtil.createId(ClassBManyToMany.class)); bInst1.setLabel("Instance (1) of ClassB"); modelClient.create(bInst1); ClassBManyToMany bInst2 = new ClassBManyToMany(); bInst2.setId(URIUtil.createId(ClassBManyToMany.class)); bInst2.setLabel("Instance (2) of ClassB"); modelClient.create(bInst2); StringSet bIds = new StringSet(); bIds.add(bInst1.getId().toString()); bIds.add(bInst2.getId().toString()); ClassAManyToMany aInst1 = new ClassAManyToMany(); aInst1.setId(URIUtil.createId(ClassAManyToMany.class)); aInst1.setLabel("Instance (1) of ClassA"); aInst1.setBids(bIds); modelClient.create(aInst1); ClassAManyToMany aInst2 = new ClassAManyToMany(); aInst2.setId(URIUtil.createId(ClassAManyToMany.class)); aInst2.setLabel("Instance (2) of ClassA"); aInst2.setBids(bIds); modelClient.create(aInst2); StringSet aIds = new StringSet(); aIds.add(aInst1.getId().toString()); aIds.add(aInst2.getId().toString()); bInst1.setAids(aIds); modelClient.update(bInst1); bInst2.setAids(aIds); modelClient.update(bInst1); ClassAManyToMany qAinst1 = modelClient.find(ClassAManyToMany.class, aInst1.getId()); List<ClassBManyToMany> a1LazyLoadedBs = qAinst1.getBinstances(); Assert.assertNotNull(a1LazyLoadedBs); Assert.assertEquals(2, a1LazyLoadedBs.size()); ClassAManyToMany qAinst2 = modelClient.find(ClassAManyToMany.class, aInst1.getId()); List<ClassBManyToMany> a2LazyLoadedBs = qAinst2.getBinstances(); Assert.assertNotNull(a2LazyLoadedBs); Assert.assertEquals(2, a2LazyLoadedBs.size()); ClassBManyToMany qBinst1 = modelClient.find(ClassBManyToMany.class, bInst1.getId()); List<ClassAManyToMany> b1LazyLoadedAinstList = qBinst1.getAinstances(); Assert.assertNotNull(b1LazyLoadedAinstList); Assert.assertEquals(2, b1LazyLoadedAinstList.size()); ClassBManyToMany qBinst2 = modelClient.find(ClassBManyToMany.class, bInst1.getId()); List<ClassAManyToMany> b2LazyLoadedAinstList = qBinst2.getAinstances(); Assert.assertNotNull(b2LazyLoadedAinstList); Assert.assertEquals(2, b2LazyLoadedAinstList.size()); } // The following inheritance structure exists for the below test (inheritanceTest()): // // DataObject (a) // ^ // | // BlockObject (a) --------o VirtualArray (BlockObject contains a VirtualArray) // ^ // / \ // / \ // BlockSnapshot Volume // ^ // | // BlockMirror // @Test public void inheritanceTest() { try { URI vArrayId = createDbObject(VirtualArray.class, 1).iterator().next().getId(); URI vArrayId2 = createDbObject(VirtualArray.class, 1).iterator().next().getId(); List<Volume> vols = createDbObject(Volume.class, 5); for (Volume vol : vols) { vol.setVirtualArray(vArrayId); } modelClient.update(vols); List<BlockMirror> mirrors = createDbObject(BlockMirror.class, 5); for (BlockMirror mirror : mirrors) { mirror.setVirtualArray(vArrayId); } modelClient.update(mirrors); List<BlockSnapshot> snapshots = createDbObject(BlockSnapshot.class, 3); for (BlockSnapshot snapshot : snapshots) { snapshot.setVirtualArray(vArrayId); } modelClient.update(snapshots); // get all volumes for a varray using lazy loading VirtualArray qVarray = modelClient.find(VirtualArray.class, vArrayId); Assert.assertNotNull(qVarray.getVolumes()); Assert.assertEquals(5, qVarray.getVolumes().size()); // get the varray for a volume using lazy loading Volume qVol = modelClient.find(Volume.class, vols.iterator().next().getId()); Assert.assertNotNull(qVol.getVirtualArrayObj()); Assert.assertEquals(vArrayId, qVol.getVirtualArrayObj().getId()); // get all block mirrors for a varray using lazy loading VirtualArray qVarray2 = modelClient.find(VirtualArray.class, vArrayId); Assert.assertNotNull(qVarray2.getVolumes()); Assert.assertEquals(5, qVarray2.getVolumes().size()); // get the virtual array for a block mirror using lazy loading BlockMirror qMirror = modelClient.find(BlockMirror.class, mirrors.iterator().next().getId()); Assert.assertNotNull(qMirror.getVirtualArrayObj()); Assert.assertEquals(vArrayId, qMirror.getVirtualArrayObj().getId()); // get all volumes for a varray using joiner List<Volume> volsFromJoiner = modelClient.join(VirtualArray.class, "one").match("label", qVarray.getLabel()) .join("one", Volume.class, "two", "varray").go().list("two"); Assert.assertEquals(5, volsFromJoiner.size()); // get all mirrors for a varray using lazy loader List<BlockMirror> mirrorsFromJoiner = modelClient.join(VirtualArray.class, "one").match("label", qVarray.getLabel()) .join("one", BlockMirror.class, "two", "varray").go().list("two"); Assert.assertEquals(5, mirrorsFromJoiner.size()); // get the varray for a volume using Joiner Volume volume = mirrors.iterator().next(); List<VirtualArray> volvArrayFromJoiner = modelClient.join(Volume.class, "one").match("label", volume.getLabel()) .join("one", "varray", VirtualArray.class, "two").go().list("two"); Assert.assertEquals(1, volvArrayFromJoiner.size()); // get the varray for a mirror using joiner BlockMirror mirror = mirrors.iterator().next(); List<VirtualArray> mirrorvArrayFromJoiner = modelClient.join(BlockMirror.class, "one").match("label", mirror.getLabel()) .join("one", "varray", VirtualArray.class, "two").go().list("two"); Assert.assertEquals(1, mirrorvArrayFromJoiner.size()); // get all volumes and mirrors for a varray using joiner List<BlockObject> allBlockObjects = modelClient.join(VirtualArray.class, "one").match("label", qVarray.getLabel()) .join("one", BlockObject.class, "two", "varray").go().list("two"); Assert.assertEquals(13, allBlockObjects.size()); } catch (InstantiationException | IllegalAccessException e) { _log.error(e.getMessage(), e); Assert.fail(e.getMessage()); } } }