package org.dcache.services.info.secondaryInfoProviders; import com.google.common.collect.Sets; import org.junit.Before; import org.junit.Test; import java.util.HashSet; import java.util.Set; import org.dcache.services.info.base.MalleableStateTransition; import org.dcache.services.info.base.PostTransitionStateExhibitor; import org.dcache.services.info.base.QueuingStateUpdateManager; import org.dcache.services.info.base.StateExhibitor; import org.dcache.services.info.base.StatePath; import org.dcache.services.info.base.StateUpdate; import org.dcache.services.info.base.StateWatcher; import org.dcache.services.info.base.TestStateExhibitor; import org.dcache.services.info.stateInfo.LinkInfo; import org.dcache.services.info.stateInfo.SpaceInfo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; // FIXME the tests do not check that pools are partitioned correctly. public class NormalisedAccessSpaceMaintainerTests { public static final StatePath PATH_NAS = new StatePath("nas"); public static final StatePath PATH_NAS_INACCESSIBLE = PATH_NAS.newChild( NormalisedAccessSpaceMaintainer.PaintInfo.NAS_NAME_INACCESSIBLE); TestStateExhibitor _exhibitor; StateWatcher _watcher; QueuingStateUpdateManager _sum; StateUpdate _update; MalleableStateTransition _transition; @Before public void setUp() { _exhibitor = new TestStateExhibitor(); _watcher = new NormalisedAccessSpaceMaintainer(); _sum = new QueuingStateUpdateManager(); _update = new StateUpdate(); _transition = new MalleableStateTransition(); } /** * State is empty. We add a poolgroup. */ @Test public void testEmptyNewPoolgroup() { String poolgroupName = "new-poolgroup"; StateLocation.transitionAddsPoolgroup( _transition, poolgroupName, 0); triggerWatcher(); // we expect NASM to establish a NAS. assertEquals( "checking number of purges", 0, _update.countPurges()); assertEquals( "checking number of metrics", 0, _update.count()); } /** * State is empty. We add a pool, but no space metrics yet */ @Test public void testEmptyNewPool() { String poolName = "new-poolgroup"; StateLocation.transitionAddsPool( _transition, poolName, 0); triggerWatcher(); // we expect NASM to establish a NAS. assertEquals( "checking number of purges", 0, _update.countPurges()); assertTrue( "checking number of metrics", _update.count() != 0); } /** * State is empty. We add a pool with space metrics. */ @Test public void testEmptyNewPoolWithSpaceMetrics() { String poolName = "pool-0"; StateLocation.transitionAddsPoolMetrics( _transition, poolName, 0, new SpaceInfo( 10, 8, 1, 1)); triggerWatcher(); // Structure hasn't changed, we don't purge. assertEquals( "checking number of purges", 0, _update.countPurges()); // Assert that there is a NAS Set<String> expectedPools = new HashSet<>(); expectedPools.add( poolName); assertNas( _update, PATH_NAS_INACCESSIBLE, expectedPools, new SpaceInfo( 10, 8, 1, 1)); } /** * State is empty. We add two pools with space metrics. */ @Test public void testEmptyTwoNewPoolsWithSpaceMetrics() { String pool1Name = "pool-1"; String pool2Name = "pool-2"; StateLocation.transitionAddsPoolMetrics( _transition, pool1Name, 0, new SpaceInfo( 10, 8, 1, 1)); StateLocation.transitionAddsPoolMetrics( _transition, pool2Name, 1, new SpaceInfo( 20, 16, 2, 2)); triggerWatcher(); // Structure hasn't changed, we don't purge. assertEquals( "checking number of purges", 0, _update.countPurges()); // Assert that there is a NAS Set<String> expectedPools = new HashSet<>(); expectedPools.add( pool1Name); expectedPools.add( pool2Name); assertNas( _update, PATH_NAS_INACCESSIBLE, expectedPools, new SpaceInfo( 30, 24, 3, 3)); } /** * State has a pool with space metrics. We update these * metrics. */ @Test public void testPoolWithMetricsUpdatePoolMetrics() { String poolName = "pool-0"; StateLocation.putPoolSpaceMetrics( _exhibitor, poolName, new SpaceInfo( 10, 8, 1, 1)); StateLocation.transitionAddsPoolMetrics( _transition, poolName, 4, new SpaceInfo( 10, 6, 2, 2)); triggerWatcher(); Set<String> expectedPools = new HashSet<>(); expectedPools.add( poolName); assertNas( _update, PATH_NAS_INACCESSIBLE, expectedPools, new SpaceInfo( 10, 6, 2, 2)); } /** * State has a link with no access prefs. We add a pool to this link that has no * space metrics. */ @Test public void testLinkTransitionAddsPoolInLink() { String linkName = "link-1"; String poolName = "pool-1"; StateLocation.putLink( _exhibitor, linkName); StateLocation.transitionAddsPoolInLink( _transition, linkName, poolName, 2); triggerWatcher(); assertEquals( "checking number of purges", 1, _update.countPurges()); Set<String> expectedPools = new HashSet<>(); expectedPools.add( poolName); assertNas( _update, PATH_NAS.newChild(linkName), expectedPools, new SpaceInfo( 0, 0, 0, 0)); } /** * State has a pool with space metrics and link. Transition adds that pool to the link */ @Test public void testLinkAndPoolWithSpaceMetricsTransitionAddsPoolInLink() { String linkName = "link-1"; String poolName = "pool-1"; SpaceInfo poolInfo = new SpaceInfo( 10, 8, 1, 1); StateLocation.putPoolSpaceMetrics( _exhibitor, poolName, poolInfo); StateLocation.putLink( _exhibitor, linkName); StateLocation.transitionAddsPoolInLink( _transition, linkName, poolName, 2); triggerWatcher(); assertEquals( "checking number of purges", 1, _update.countPurges()); Set<String> expectedPools = new HashSet<>(); expectedPools.add( poolName); assertNas( _update, PATH_NAS.newChild(linkName), expectedPools, poolInfo); } /** * State has a pool with space metrics within a link. Transition adds a new pool * with space metrics. */ @Test public void testLinkAndPoolWithSpaceMetricsTransitionAddsPoolWithMetrics() { String linkName = "link-1"; String pool1Name = "pool-1"; String pool2Name = "pool-2"; SpaceInfo pool1Info = new SpaceInfo( 10, 8, 1, 1); SpaceInfo pool2Info = new SpaceInfo( 20, 16, 2, 2); StateLocation.putPoolSpaceMetrics( _exhibitor, pool1Name, pool1Info); StateLocation.putPoolInLink( _exhibitor, linkName, pool1Name); StateLocation.transitionAddsPoolMetrics( _transition, pool2Name, 1, pool2Info); triggerWatcher(); assertEquals( "checking number of purges", 0, _update.countPurges()); assertNas( _update, PATH_NAS_INACCESSIBLE, Sets.newHashSet(pool2Name), pool2Info); } @Test public void testNoUnitsAddLinkZeroPrefs() { String linkName = "link-1"; String poolName = "pool-1"; SpaceInfo poolInfo = new SpaceInfo( 10, 8, 1, 1); StateLocation.putPoolSpaceMetrics( _exhibitor, poolName, poolInfo); StateLocation.putPoolInLink( _exhibitor, linkName, poolName); StateLocation.transitionAddsLinkPrefs( _transition, linkName, 2, 0, 0, 0, 0); triggerWatcher(); assertEquals( "checking number of purges", 1, _update.countPurges()); Set<String> expectedPools = new HashSet<>(); expectedPools.add( poolName); assertNas( _update, PATH_NAS.newChild(linkName), expectedPools, poolInfo); } @Test public void testNoUnitsAddLinkCanReadPrefs() { String linkName = "link-1"; String poolName = "pool-1"; SpaceInfo poolInfo = new SpaceInfo( 10, 8, 1, 1); StateLocation.putPoolSpaceMetrics( _exhibitor, poolName, poolInfo); StateLocation.putPoolInLink( _exhibitor, linkName, poolName); StateLocation.transitionAddsLinkPrefs( _transition, linkName, 2, 5, 0, 0, 0); triggerWatcher(); assertEquals( "checking number of purges", 1, _update.countPurges()); Set<String> expectedPools = new HashSet<>(); expectedPools.add( poolName); assertNas( _update, PATH_NAS.newChild(linkName), expectedPools, poolInfo); } @Test public void testStoreUnitsAddLinkZeroPrefs() { String linkName = "link-1"; String poolName = "pool-1"; SpaceInfo poolInfo = new SpaceInfo( 10, 8, 1, 1); StateLocation.putPoolSpaceMetrics( _exhibitor, poolName, poolInfo); StateLocation.putPoolInLink( _exhibitor, linkName, poolName); StateLocation.putUnitInLink( _exhibitor, linkName, LinkInfo.UNIT_TYPE.STORE, "dcache@osm"); StateLocation.transitionAddsLinkPrefs( _transition, linkName, 2, 0, 0, 0, 0); triggerWatcher(); assertEquals( "checking number of purges", 1, _update.countPurges()); Set<String> expectedPools = new HashSet<>(); expectedPools.add( poolName); assertNas( _update, PATH_NAS.newChild(linkName), expectedPools, poolInfo); } @Test public void testStoreUnitsAddLinkCanReadPrefs() { String linkName = "link-1"; String poolName = "pool-1"; SpaceInfo poolInfo = new SpaceInfo( 10, 8, 1, 1); StateLocation.putPoolSpaceMetrics( _exhibitor, poolName, poolInfo); StateLocation.putPoolInLink( _exhibitor, linkName, poolName); StateLocation.putUnitInLink( _exhibitor, linkName, LinkInfo.UNIT_TYPE.STORE, "dcache@osm"); StateLocation.transitionAddsLinkPrefs( _transition, linkName, 2, 5, 0, 0, 0); triggerWatcher(); assertEquals( "checking number of purges", 1, _update.countPurges()); Set<String> expectedPools = new HashSet<>(); expectedPools.add( poolName); assertNas( _update, PATH_NAS.newChild("link-1"), expectedPools, poolInfo); } @Test public void testStoreUnitsAddReadWriteLink() { String linkName = "link-1"; String poolName = "pool-1"; SpaceInfo poolInfo = new SpaceInfo( 10, 8, 1, 1); StateLocation.putPoolSpaceMetrics( _exhibitor, poolName, poolInfo); StateLocation.putPoolInLink( _exhibitor, linkName, poolName); StateLocation.putUnitInLink( _exhibitor, linkName, LinkInfo.UNIT_TYPE.STORE, "dcache@osm"); StateLocation.transitionAddsLinkPrefs( _transition, linkName, 2, 5, 5, 0, 0); triggerWatcher(); assertEquals( "checking number of purges", 1, _update.countPurges()); Set<String> expectedPools = new HashSet<>(); expectedPools.add( poolName); assertNas( _update, PATH_NAS.newChild("link-1"), expectedPools, poolInfo); } @Test public void testStoreUnitsAddReadWriteLinkAddReadLink() { String link1Name = "link-1"; String link2Name = "link-2"; String poolName = "pool-1"; SpaceInfo poolInfo = new SpaceInfo( 10, 8, 1, 1); StateLocation.putPoolSpaceMetrics( _exhibitor, poolName, poolInfo); StateLocation.putPoolInLink( _exhibitor, link1Name, poolName); StateLocation.putUnitInLink( _exhibitor, link1Name, LinkInfo.UNIT_TYPE.STORE, "dcache@osm"); StateLocation.putPoolInLink( _exhibitor, link2Name, poolName); StateLocation.putUnitInLink( _exhibitor, link2Name, LinkInfo.UNIT_TYPE.STORE, "atlas@osm"); StateLocation.transitionAddsLinkPrefs( _transition, link1Name, 2, 5, 5, 0, 0); StateLocation.transitionAddsLinkPrefs( _transition, link2Name, 2, 5, 0, 0, 0); triggerWatcher(); assertEquals( "checking number of purges", 1, _update.countPurges()); Set<String> expectedPools = new HashSet<>(); expectedPools.add( poolName); assertNas( _update, PATH_NAS.newChild("link-1,link-2"), expectedPools, poolInfo); } /* * ADD TWO POOLS THAT END UP IN DIFFERENT NAS */ @Test public void testTwoPoolsDifferingInLinks() { String pool1Name = "pool-1"; String pool2Name = "pool-2"; String link1Name = "link-1"; String link2Name = "link-2"; SpaceInfo pool1Info = new SpaceInfo( 10, 8, 1, 1); SpaceInfo pool2Info = new SpaceInfo( 20, 16, 2, 2); StateLocation.putPoolSpaceMetrics( _exhibitor, pool1Name, pool1Info); StateLocation.putPoolInLink( _exhibitor, link1Name, pool1Name); StateLocation.putPoolSpaceMetrics( _exhibitor, pool2Name, pool2Info); StateLocation.putPoolInLink( _exhibitor, link2Name, pool2Name); // Add the same unit selecting the different links. StateLocation.putUnitInLink( _exhibitor, link1Name, LinkInfo.UNIT_TYPE.STORE, "dcache@osm"); StateLocation.putUnitInLink( _exhibitor, link2Name, LinkInfo.UNIT_TYPE.STORE, "dcache@osm"); StateLocation.transitionAddsLinkPrefs( _transition, link1Name, 2, 5, 0, 0, 0); StateLocation.transitionAddsLinkPrefs( _transition, link2Name, 2, 5, 0, 0, 0); triggerWatcher(); assertNas(_update, PATH_NAS.newChild("link-1"), Sets.newHashSet(pool1Name), new SpaceInfo(pool1Info)); assertNas(_update, PATH_NAS.newChild("link-2"), Sets.newHashSet(pool2Name), new SpaceInfo(pool2Info)); } /** * Check that a NAS metrics are being updated. */ private void assertNas( StateUpdate update, StatePath nasPath, Set<String> pools, SpaceInfo info) { StatePath poolsPath = nasPath.newChild( "pools"); for( String pool : pools) { StateLocation .assertUpdateHasBranch("checking for pool " + pool, update, poolsPath .newChild(pool)); } StateLocation.assertSpaceMetrics( update, nasPath.newChild( "space"), info); } private void triggerWatcher() { StateExhibitor futureState = new PostTransitionStateExhibitor( _exhibitor, _transition); _watcher.trigger( _update, _exhibitor, futureState); } }