package org.dcache.tests.pool.migration; import com.google.common.collect.ImmutableList; import org.junit.Before; import org.junit.Test; import org.parboiled.Parboiled; import org.parboiled.parserunners.BasicParseRunner; import org.parboiled.support.ParsingResult; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.regex.Pattern; import diskCacheV111.pools.PoolCostInfo; import diskCacheV111.vehicles.PoolManagerPoolInformation; import org.dcache.pool.classic.IoQueueManager; import org.dcache.pool.migration.PoolListFilter; import org.dcache.pool.migration.RefreshablePoolList; import org.dcache.pool.migration.SymbolTable; import org.dcache.util.Glob; import org.dcache.util.expression.Expression; import org.dcache.util.expression.ExpressionParser; import org.dcache.util.expression.TypeMismatchException; import org.dcache.util.expression.UnknownIdentifierException; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.hasSize; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; public class PoolListFilterTest { private final PoolManagerPoolInformation POOL1 = createPool("pool1"); private final PoolManagerPoolInformation POOL2 = createPool("pool2"); private final PoolManagerPoolInformation POOL3 = createPool("pool3"); private final PoolManagerPoolInformation SOURCE = createPool("source"); private SymbolTable symbols; @Before public void setup() { symbols = new SymbolTable(); symbols.put("source", POOL1); symbols.put("target", POOL1); } @Test public void testExclude() { PoolList list = PoolList.newOnlineList(POOL1, POOL2, POOL3); PoolListFilter filter = createFilter(list, "*1", "false", null, "true", SOURCE); List<PoolManagerPoolInformation> result = filter.getPools(); assertEquals(2, result.size()); assertDoesNotContainPool(POOL1, result); assertContainsPool(POOL2, result); assertContainsPool(POOL3, result); } @Test public void testExcludeOffline() { PoolList list = PoolList.newOfflineList("pool1", "pool2", "pool3"); PoolListFilter filter = createFilter(list, "*1", "false", null, "true", SOURCE); List<String> result = filter.getOfflinePools(); assertThat(result, hasSize(2)); assertThat(result, containsInAnyOrder("pool2", "pool3")); } @Test public void testExcludeWhen() { PoolList list = PoolList.newOnlineList(POOL1, POOL2, POOL3); PoolListFilter filter = createFilter(list, null, "target.name=~'pool[12]'", null, "true", SOURCE); List<PoolManagerPoolInformation> result = filter.getPools(); assertEquals(1, result.size()); assertDoesNotContainPool(POOL1, result); assertDoesNotContainPool(POOL2, result); assertContainsPool(POOL3, result); } @Test public void testInclude() { PoolList list = PoolList.newOnlineList(POOL1, POOL2, POOL3); PoolListFilter filter = createFilter(list, null, "false", "*1", "true", SOURCE); List<PoolManagerPoolInformation> result = filter.getPools(); assertEquals(1, result.size()); assertContainsPool(POOL1, result); assertDoesNotContainPool(POOL2, result); assertDoesNotContainPool(POOL3, result); } @Test public void testIncludeOffline() { PoolList list = PoolList.newOfflineList("pool1", "pool2", "pool3"); PoolListFilter filter = createFilter(list, null, "false", "*1", "true", SOURCE); List<String> result = filter.getOfflinePools(); assertThat(result, hasSize(1)); assertThat(result, contains("pool1")); } @Test public void testIncludeWhen() { PoolList list = PoolList.newOnlineList(POOL1, POOL2, POOL3); PoolListFilter filter = createFilter(list, null, "false", null, "target.name=~'pool[12]'", SOURCE); List<PoolManagerPoolInformation> result = filter.getPools(); assertEquals(2, result.size()); assertContainsPool(POOL1, result); assertContainsPool(POOL2, result); assertDoesNotContainPool(POOL3, result); } @Test public void testBothIncludedAndExcluded() { PoolList list = PoolList.newOnlineList(POOL1, POOL2, POOL3); PoolListFilter filter = createFilter(list, "*1", "false", "*1", "true", SOURCE); List<PoolManagerPoolInformation> result = filter.getPools(); assertEquals(0, result.size()); } @Test public void testBothIncludedWhenAndExcludedWhen() { PoolList list = PoolList.newOnlineList(POOL1, POOL2, POOL3); PoolListFilter filter = createFilter(list, null, "target.name=='pool1'", null, "target.name=='pool1'", SOURCE); List<PoolManagerPoolInformation> result = filter.getPools(); assertEquals(0, result.size()); } @Test public void testFilterRefersToSource() { PoolList list = PoolList.newOnlineList(POOL1, POOL2, POOL3); PoolListFilter filter = createFilter(list, null, "source.name=='source'", null, "true", SOURCE); List<PoolManagerPoolInformation> result = filter.getPools(); assertEquals(0, result.size()); } @Test public void testCacheInvalidation() { PoolList list = PoolList.newOnlineList(POOL1, POOL2, POOL3); PoolListFilter filter = createFilter(list, null, "false", null, "target.name=~'pool[12]'", SOURCE); List<PoolManagerPoolInformation> result = filter.getPools(); assertEquals(2, result.size()); assertContainsPool(POOL1, result); assertContainsPool(POOL2, result); assertDoesNotContainPool(POOL3, result); list.setPools(POOL2, POOL3); result = filter.getPools(); assertEquals(1, result.size()); assertDoesNotContainPool(POOL1, result); assertContainsPool(POOL2, result); assertDoesNotContainPool(POOL3, result); } private Expression createExpression(String s) { if (s == null) { return null; } ExpressionParser parser = Parboiled.createParser(ExpressionParser.class); ParsingResult<Expression> result = new BasicParseRunner(parser.Top()).run(s); try { result.resultValue.check(symbols); } catch (TypeMismatchException | UnknownIdentifierException e) { fail(e.toString()); } return result.resultValue; } private static PoolManagerPoolInformation createPool(String name) { return new PoolManagerPoolInformation(name, new PoolCostInfo(name, IoQueueManager.DEFAULT_QUEUE), 0); } private static Set<Pattern> createPatterns(String glob) { Set<Pattern> patterns = new HashSet<>(); if (glob != null) { patterns.add(Glob.parseGlobToPattern(glob)); } return patterns; } private PoolListFilter createFilter(RefreshablePoolList list, String exclude, String excludeWhen, String include, String includeWhen, PoolManagerPoolInformation source) { return new PoolListFilter(list, createPatterns(exclude), createExpression(excludeWhen), createPatterns(include), createExpression(includeWhen), PoolList.newOnlineList(source)); } private static boolean containsPool(String name, List<PoolManagerPoolInformation> list) { for (PoolManagerPoolInformation pool: list) { if (pool.getName().equals(name)) { return true; } } return false; } private static void assertContainsPool(PoolManagerPoolInformation pool, List<PoolManagerPoolInformation> list) { String name = pool.getName(); if (!containsPool(name, list)) { fail("Expected pool " + name + " is not in list " + list); } } private static void assertDoesNotContainPool(PoolManagerPoolInformation pool, List<PoolManagerPoolInformation> list) { String name = pool.getName(); if (containsPool(name, list)) { fail("Unexpected pool " + name + " is in list " + list); } } /** * The object we want to test is abstract, hence we need to * subclass to test it. */ static class PoolList implements RefreshablePoolList { private ImmutableList<PoolManagerPoolInformation> _list; private ImmutableList<String> _offlinePools; public PoolList(PoolManagerPoolInformation[] pools, String[] offlinePools) { setPools(pools); setOfflinePools(offlinePools); } public static PoolList newOfflineList(String... pools) { return new PoolList(new PoolManagerPoolInformation[0], pools); } public static PoolList newOnlineList(PoolManagerPoolInformation... pools) { return new PoolList(pools, new String[0]); } @Override public boolean isValid() { return true; } public void setPools(PoolManagerPoolInformation... pools) { _list = ImmutableList.copyOf(pools); } public void setOfflinePools(String... pools) { _offlinePools = ImmutableList.copyOf(pools); } @Override public void refresh() { } @Override public ImmutableList<String> getOfflinePools() { return _offlinePools; } @Override public ImmutableList<PoolManagerPoolInformation> getPools() { return _list; } } }