package org.dcache.services.info.stateInfo;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.ConsoleAppender;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.dcache.services.info.base.IntegerStateValue;
import org.dcache.services.info.base.StatePath;
import org.dcache.services.info.base.TestStateExhibitor;
import org.dcache.services.info.secondaryInfoProviders.StateLocation;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* Test the LinkInfoVisitor class.
*/
public class LinkInfoVisitorTests {
static final StatePath LINKS_PATH = new StatePath( "links");
static final private String CONSOLE_APPENDER_NAME = "console";
static final private String CONSOLE_APPENDER_PATTERN = "%-5level - %msg%n";
/**
* Direct all warning or more severe messages from ListInfoVisitor
* log4j target to the console.
*
* FIXME: This should be done by a generic configuration file
* specified as a system property in ant.
*/
static {
LoggerContext loggerContext =
(LoggerContext) LoggerFactory.getILoggerFactory();
loggerContext.reset();
ConsoleAppender<ILoggingEvent> ca =
new ConsoleAppender<>();
ca.setContext(loggerContext);
ca.setName(CONSOLE_APPENDER_NAME);
PatternLayoutEncoder pl = new PatternLayoutEncoder();
pl.setContext(loggerContext);
pl.setPattern(CONSOLE_APPENDER_PATTERN);
pl.start();
ca.setEncoder(pl);
ca.start();
Logger logger = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
logger.addAppender(ca);
logger.setLevel(Level.WARN);
}
/** A mapping between operation preference to the name of the corresponding metric */
static final Map<LinkInfo.OPERATION,String> OPERATION_METRIC_NAME = Collections.unmodifiableMap( new HashMap<LinkInfo.OPERATION,String>() {
private static final long serialVersionUID = 2219445130285814842L;
{
put( LinkInfo.OPERATION.CACHE, "cache");
put( LinkInfo.OPERATION.P2P, "p2p");
put( LinkInfo.OPERATION.READ, "read");
put( LinkInfo.OPERATION.WRITE, "write");
}});
/** A mapping between unit type to the name of the corresponding branch */
static final Map<LinkInfo.UNIT_TYPE,String> UNIT_TYPE_METRIC_NAME = Collections.unmodifiableMap( new HashMap<LinkInfo.UNIT_TYPE,String>() {
private static final long serialVersionUID = -4333350816329550714L;
{
put( LinkInfo.UNIT_TYPE.DCACHE, "dcache");
put( LinkInfo.UNIT_TYPE.NETWORK, "net");
put( LinkInfo.UNIT_TYPE.PROTOCOL, "protocol");
put( LinkInfo.UNIT_TYPE.STORE, "store");
}});
TestStateExhibitor _exhibitor;
LinkInfoVisitor _visitor;
@Before
public void setUp()
{
_exhibitor = new TestStateExhibitor();
_visitor = new LinkInfoVisitor();
}
@Test
public void testEmptyState() {
_exhibitor.visitState( _visitor);
Map<String,LinkInfo> acquiredInfo = _visitor.getInfo();
assertEquals( "", 0, acquiredInfo.size());
}
@Test
public void testSingleEmptyLink() {
Set<String> linkNames = new HashSet<>();
linkNames.add( "link-1");
assertEmptyLinksOk( linkNames);
}
@Test
public void testTwoEmptyLink() {
Set<String> linkNames = new HashSet<>();
linkNames.add( "link-1");
linkNames.add( "link-2");
assertEmptyLinksOk( linkNames);
}
@Test
public void testLinkWithSinglePool() {
Set<String> pools = new HashSet<>();
pools.add( "a pool");
assertLinkWithPoolsOk( pools);
}
@Test
public void testLinkWithSpaceMetrics() {
String linkName = "link-1";
long totalSpace = 10;
long freeSpace = 8;
long preciousSpace = 1;
long removableSpace = 1;
StateLocation.putLink( _exhibitor, linkName);
SpaceInfo linkSpace = new SpaceInfo( totalSpace, freeSpace, preciousSpace, removableSpace);
StateLocation.putLinkSpaceMetrics( _exhibitor, linkName, linkSpace);
LinkInfo expectedLinkInfo = new LinkInfo(linkName);
assertSingleLinkInfo( linkName, expectedLinkInfo);
}
@Test
public void testLinkWithTwoPools() {
Set<String> pools = new HashSet<>();
pools.add( "a pool");
pools.add( "another pool");
assertLinkWithPoolsOk( pools);
}
@Test
public void testLinkWithThreePools() {
Set<String> pools = new HashSet<>();
pools.add( "a pool");
pools.add( "another pool");
pools.add( "a third pool");
assertLinkWithPoolsOk( pools);
}
@Test
public void testLinkWithSinglePoolgroup() {
Set<String> poolgroups = new HashSet<>();
poolgroups.add( "a poolgroup");
assertLinkWithPoolgroupsOk( poolgroups);
}
@Test
public void testLinkWithTwoPoolgroups() {
Set<String> poolgroups = new HashSet<>();
poolgroups.add( "a poolgroup");
poolgroups.add( "another poolgroup");
assertLinkWithPoolgroupsOk( poolgroups);
}
@Test
public void testLinkWithThreePoolgroup() {
Set<String> poolgroups = new HashSet<>();
poolgroups.add( "a poolgroup");
poolgroups.add( "another poolgroup");
poolgroups.add( "a third poolgroup");
assertLinkWithPoolgroupsOk( poolgroups);
}
@Test
public void testLinkWithUnitgroup() {
Set<String> unitgroups = new HashSet<>();
unitgroups.add( "unitgroup");
assertLinkWithUnitgroupsOk( unitgroups);
}
@Test
public void testLinkWithTwoUnitgroups() {
Set<String> unitgroups = new HashSet<>();
unitgroups.add( "unitgroup-1");
unitgroups.add( "unitgroup-2");
assertLinkWithUnitgroupsOk( unitgroups);
}
@Test
public void testLinkWithThreeUnitgroups() {
Set<String> unitgroups = new HashSet<>();
unitgroups.add( "unitgroup-1");
unitgroups.add( "unitgroup-2");
unitgroups.add( "unitgroup-3");
assertLinkWithUnitgroupsOk( unitgroups);
}
@Test
public void testLinkWithReadPref() {
String linkName = "my link";
LinkInfo expectedLinkInfo = new LinkInfo("expected link");
addOperationPrefInLink( linkName, LinkInfo.OPERATION.READ, 5);
expectedLinkInfo.setOperationPref( LinkInfo.OPERATION.READ, 5);
assertSingleLinkInfo( linkName, expectedLinkInfo);
}
@Test
public void testLinkWithWritePref() {
String linkName = "my link";
LinkInfo expectedLinkInfo = new LinkInfo("expected link");
addOperationPrefInLink( linkName, LinkInfo.OPERATION.WRITE, 5);
expectedLinkInfo.setOperationPref( LinkInfo.OPERATION.WRITE, 5);
assertSingleLinkInfo( linkName, expectedLinkInfo);
}
@Test
public void testLinkWithP2pPref() {
String linkName = "my link";
LinkInfo expectedLinkInfo = new LinkInfo("expected link");
addOperationPrefInLink( linkName, LinkInfo.OPERATION.P2P, 5);
expectedLinkInfo.setOperationPref( LinkInfo.OPERATION.P2P, 5);
assertSingleLinkInfo( linkName, expectedLinkInfo);
}
@Test
public void testLinkWithCachePref() {
String linkName = "my link";
LinkInfo expectedLinkInfo = new LinkInfo("expected link");
addOperationPrefInLink( linkName, LinkInfo.OPERATION.CACHE, 5);
expectedLinkInfo.setOperationPref( LinkInfo.OPERATION.CACHE, 5);
assertSingleLinkInfo( linkName, expectedLinkInfo);
}
@Test
public void testLinkWithAllPrefs() {
String linkName = "my link";
LinkInfo expectedLinkInfo = new LinkInfo("expected link");
addOperationPrefInLink( linkName, LinkInfo.OPERATION.READ, 5);
addOperationPrefInLink( linkName, LinkInfo.OPERATION.WRITE, 7);
addOperationPrefInLink( linkName, LinkInfo.OPERATION.CACHE, 13);
addOperationPrefInLink( linkName, LinkInfo.OPERATION.P2P, 17);
expectedLinkInfo.setOperationPref( LinkInfo.OPERATION.READ, 5);
expectedLinkInfo.setOperationPref( LinkInfo.OPERATION.WRITE, 7);
expectedLinkInfo.setOperationPref( LinkInfo.OPERATION.CACHE, 13);
expectedLinkInfo.setOperationPref( LinkInfo.OPERATION.P2P, 17);
assertSingleLinkInfo( linkName, expectedLinkInfo);
}
@Test
public void testLinkWithStoreUnit() {
Set<String> units = new HashSet<>();
units.add("unit1");
assertLinkWithSameUnitsOk( LinkInfo.UNIT_TYPE.STORE, units);
}
@Test
public void testLinkWithTwoStoreUnits() {
Set<String> units = new HashSet<>();
units.add("unit1");
units.add("unit2");
assertLinkWithSameUnitsOk( LinkInfo.UNIT_TYPE.STORE, units);
}
@Test
public void testLinkWithDcacheUnit() {
Set<String> units = new HashSet<>();
units.add("unit1");
assertLinkWithSameUnitsOk( LinkInfo.UNIT_TYPE.DCACHE, units);
}
@Test
public void testLinkWithTwoDcacheUnits() {
Set<String> units = new HashSet<>();
units.add("unit1");
units.add("unit2");
assertLinkWithSameUnitsOk( LinkInfo.UNIT_TYPE.DCACHE, units);
}
@Test
public void testLinkWithNetUnit() {
Set<String> units = new HashSet<>();
units.add("unit1");
assertLinkWithSameUnitsOk( LinkInfo.UNIT_TYPE.NETWORK, units);
}
@Test
public void testLinkWithTwoNetUnits() {
Set<String> units = new HashSet<>();
units.add("unit1");
units.add("unit2");
assertLinkWithSameUnitsOk( LinkInfo.UNIT_TYPE.NETWORK, units);
}
@Test
public void testLinkWithProtoUnit() {
Set<String> units = new HashSet<>();
units.add("unit1");
assertLinkWithSameUnitsOk( LinkInfo.UNIT_TYPE.PROTOCOL, units);
}
@Test
public void testLinkWithTwoProtoUnits() {
Set<String> units = new HashSet<>();
units.add("unit1");
units.add("unit2");
assertLinkWithSameUnitsOk( LinkInfo.UNIT_TYPE.PROTOCOL, units);
}
/**
* PRIVATE SUPPORT METHODS
*/
/**
* Update the simulated dCache state
*/
private void addPoolInLink( String linkName, String poolName) {
_exhibitor.addBranch( LINKS_PATH.newChild( linkName).newChild( "pools").newChild( poolName));
}
private void addPoolgroupInLink( String linkName, String poolgroupName) {
_exhibitor.addBranch( LINKS_PATH.newChild( linkName).newChild( "poolgroups").newChild( poolgroupName));
}
private void addOperationPrefInLink( String linkName, LinkInfo.OPERATION operation, long value) {
_exhibitor.addMetric( LINKS_PATH.newChild( linkName).newChild( "prefs").newChild( OPERATION_METRIC_NAME.get( operation)),
new IntegerStateValue( value));
}
private void addUnitInLink( String linkName, LinkInfo.UNIT_TYPE unitType, String unit) {
_exhibitor.addBranch( LINKS_PATH.newChild( linkName).newChild( "units").newChild(UNIT_TYPE_METRIC_NAME.get( unitType)).newChild( unit));
}
private void addUnitgroupInLink( String linkName, String unitgroupName) {
_exhibitor.addBranch( LINKS_PATH.newChild( linkName).newChild( "unitgroups").newChild( unitgroupName));
}
/**
* Verify that a link with only a specified Set of pools is read correctly.
*/
private void assertLinkWithPoolsOk( Set<String> pools) {
LinkInfo expectedLinkInfo = new LinkInfo("expected link");
String linkName = "a link";
for( String poolName : pools) {
addPoolInLink( linkName, poolName);
expectedLinkInfo.addPool( poolName);
}
assertSingleLinkInfo( linkName, expectedLinkInfo);
}
private void assertLinkWithUnitgroupsOk( Set<String> unitgroups) {
LinkInfo expectedLinkInfo = new LinkInfo("expected link");
String linkName = "a link";
for( String unitgroupName : unitgroups) {
addUnitgroupInLink( linkName, unitgroupName);
expectedLinkInfo.addUnitgroup( unitgroupName);
}
assertSingleLinkInfo( linkName, expectedLinkInfo);
}
private void assertLinkWithSameUnitsOk( LinkInfo.UNIT_TYPE unitType, Set<String> units) {
String linkName = "my link";
LinkInfo expectedLinkInfo = new LinkInfo( "expected link");
for( String unitName : units) {
addUnitInLink( linkName, unitType, unitName);
expectedLinkInfo.addUnit( unitType, unitName);
}
assertSingleLinkInfo( linkName, expectedLinkInfo);
}
/**
* Verify that a link with only a specified Set of poolgroups is read correctly.
*/
private void assertLinkWithPoolgroupsOk( Set<String> poolgroups) {
LinkInfo expectedLinkInfo = new LinkInfo("expected link");
String linkName = "a link";
for( String poolgroupName : poolgroups) {
addPoolgroupInLink( linkName, poolgroupName);
expectedLinkInfo.addPoolgroup( poolgroupName);
}
assertSingleLinkInfo( linkName, expectedLinkInfo);
}
private void assertEmptyLinksOk( Set<String> linkNames) {
for( String linkName : linkNames) {
_exhibitor.addBranch(LINKS_PATH.newChild(linkName));
}
_exhibitor.visitState( _visitor);
Map<String,LinkInfo> acquiredInfo = _visitor.getInfo();
assertEquals( "number of found links", linkNames.size(), acquiredInfo.size());
LinkInfo defaultLinkInfo = new LinkInfo("a representative link");
for( String linkName : linkNames) {
LinkInfo linkInfo = acquiredInfo.get( linkName);
assertEquals( "LinkInfo for link " + linkName, defaultLinkInfo, linkInfo);
}
}
/**
* Check that when we visit the state we get a single LinkInfo that matches the expected
* properties.
* @param linkName
* @param expectedLinkInfo
*/
private void assertSingleLinkInfo( String linkName, LinkInfo expectedLinkInfo) {
_exhibitor.visitState( _visitor);
Map<String,LinkInfo> acquiredInfo = _visitor.getInfo();
assertEquals( "wrong number of LinkInfo returned", 1, acquiredInfo.size());
LinkInfo foundLinkInfo = acquiredInfo.get( linkName);
assertNotNull( "couldn't find LinkInfo for link " + linkName, foundLinkInfo);
assertEquals( "wrong information in LinkInfo for link " + linkName, expectedLinkInfo, foundLinkInfo);
}
}