Mercurial > stress-tester
changeset 1020:4678815d3051
Classes from package com.passus.st.client.filter moved to com.passus.st.filter
line wrap: on
line diff
--- a/stress-tester/src/main/java/com/passus/st/CliHelper.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/CliHelper.java Thu Mar 26 13:27:52 2020 +0100 @@ -10,8 +10,8 @@ import com.passus.net.PortRangeSet; import com.passus.net.http.session.HttpSessionAnalyzer; import com.passus.st.client.FlowExecutor; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFiltersConfigurator; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFiltersConfigurator; import com.passus.st.client.http.filter.HttpVarsFilter; import com.passus.st.emitter.Emitter; import com.passus.st.emitter.PassThroughSessionMapper;
--- a/stress-tester/src/main/java/com/passus/st/ConverterHttpClient.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/ConverterHttpClient.java Thu Mar 26 13:27:52 2020 +0100 @@ -3,8 +3,8 @@ import com.passus.commons.Assert; import com.passus.commons.service.Service; import com.passus.st.client.*; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFilterChain; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFilterChain; import com.passus.st.client.http.HttpScopes; import com.passus.st.client.http.filter.HttpFilter; import com.passus.st.client.http.filter.HttpFlowUtils;
--- a/stress-tester/src/main/java/com/passus/st/ConverterMain.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/ConverterMain.java Thu Mar 26 13:27:52 2020 +0100 @@ -1,7 +1,7 @@ package com.passus.st; import com.passus.config.ConfigurationContext; -import com.passus.st.client.filter.FlowFilter; +import com.passus.st.filter.FlowFilter; import com.passus.st.reader.nc.HttpWriteMode; import com.passus.st.source.NcEventDestination; import com.passus.st.source.PcapSessionEventSource;
--- a/stress-tester/src/main/java/com/passus/st/Main.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/Main.java Thu Mar 26 13:27:52 2020 +0100 @@ -5,7 +5,7 @@ import com.passus.commons.service.Registry; import com.passus.config.ConfigurationContext; import com.passus.st.client.*; -import com.passus.st.client.filter.FlowFilter; +import com.passus.st.filter.FlowFilter; import com.passus.st.client.http.*; import com.passus.st.emitter.SessionMapper; import com.passus.st.emitter.nio.NioEmitter;
--- a/stress-tester/src/main/java/com/passus/st/Main2.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/Main2.java Thu Mar 26 13:27:52 2020 +0100 @@ -5,7 +5,7 @@ import com.passus.commons.service.Registry; import com.passus.config.ConfigurationContext; import com.passus.st.client.*; -import com.passus.st.client.filter.FlowFilter; +import com.passus.st.filter.FlowFilter; import com.passus.st.client.http.*; import com.passus.st.emitter.SessionMapper; import com.passus.st.emitter.nio.NioEmitter;
--- a/stress-tester/src/main/java/com/passus/st/ReaderMain.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/ReaderMain.java Thu Mar 26 13:27:52 2020 +0100 @@ -6,7 +6,7 @@ import com.passus.st.client.Event; import com.passus.st.client.SessionPayloadEvent; import com.passus.st.client.SessionStatusEvent; -import com.passus.st.client.filter.MessagePredicate; +import com.passus.st.filter.MessagePredicate; import com.passus.st.emitter.SessionInfo; import com.passus.st.filter.Transformers; import com.passus.st.source.EventSource;
--- a/stress-tester/src/main/java/com/passus/st/client/FilterAware.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/FilterAware.java Thu Mar 26 13:27:52 2020 +0100 @@ -1,6 +1,6 @@ package com.passus.st.client; -import com.passus.st.client.filter.FlowFilter; +import com.passus.st.filter.FlowFilter; import java.util.Collection; import java.util.List;
--- a/stress-tester/src/main/java/com/passus/st/client/Flow.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/Flow.java Thu Mar 26 13:27:52 2020 +0100 @@ -1,7 +1,7 @@ package com.passus.st.client; import com.passus.config.Configurable; -import com.passus.st.client.filter.FlowFilter; +import com.passus.st.filter.FlowFilter; import com.passus.st.emitter.Emitter; import com.passus.st.metric.MetricSource;
--- a/stress-tester/src/main/java/com/passus/st/client/FlowExecutor.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/FlowExecutor.java Thu Mar 26 13:27:52 2020 +0100 @@ -13,9 +13,9 @@ import com.passus.config.validation.EnumValidator; import com.passus.config.validation.Errors; import com.passus.config.validation.LongValidator; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFilterChain; -import com.passus.st.client.filter.FlowFilterNodeDefinitionCreator; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFilterChain; +import com.passus.st.filter.FlowFilterNodeDefinitionCreator; import com.passus.st.emitter.Emitter; import com.passus.st.metric.MetricSource; import com.passus.st.metric.MetricsContainer;
--- a/stress-tester/src/main/java/com/passus/st/client/FlowWorker.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/FlowWorker.java Thu Mar 26 13:27:52 2020 +0100 @@ -3,7 +3,7 @@ import com.passus.commons.Assert; import com.passus.commons.time.TimeAware; import com.passus.commons.time.TimeGenerator; -import com.passus.st.client.filter.FlowFilterChain; +import com.passus.st.filter.FlowFilterChain; import com.passus.st.emitter.Emitter; import com.passus.st.emitter.EmitterHandler; import com.passus.st.emitter.SessionInfo;
--- a/stress-tester/src/main/java/com/passus/st/client/dns/filter/DnsFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/dns/filter/DnsFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -2,7 +2,7 @@ import com.passus.net.dns.DnsRecord; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FlowFilter; +import com.passus.st.filter.FlowFilter; public abstract class DnsFilter implements FlowFilter {
--- a/stress-tester/src/main/java/com/passus/st/client/dns/filter/DnsRecordTypeFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/dns/filter/DnsRecordTypeFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -9,7 +9,7 @@ import com.passus.net.dns.DnsRecord; import com.passus.net.dns.DnsRecordType; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FlowFilter; +import com.passus.st.filter.FlowFilter; import com.passus.st.plugin.PluginConstants; import java.util.Collections;
--- a/stress-tester/src/main/java/com/passus/st/client/filter/CounterFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.commons.annotations.Plugin; -import com.passus.config.Configuration; -import com.passus.config.ConfigurationContext; -import com.passus.config.annotations.NodeDefinitionCreate; -import com.passus.config.schema.NodeDefinition; -import com.passus.config.schema.NodeDefinitionCreator; -import com.passus.st.client.FlowContext; -import com.passus.st.plugin.PluginConstants; - -import java.util.concurrent.atomic.AtomicInteger; - -import static com.passus.config.schema.ConfigurationSchemaBuilder.*; - -/** - * - * @author mikolaj.podbielski - */ -@NodeDefinitionCreate(CounterFilter.NodeDefCreator.class) -@Plugin(name = CounterFilter.TYPE, category = PluginConstants.CATEGORY_FLOW_FILTER) -public class CounterFilter implements FlowFilter { - - public static final String TYPE = "counter"; - - private static final AtomicInteger ID = new AtomicInteger(); - - private MessagePredicate predicate; - private String name; - private int limit; - private CounterListener listener = (e) -> { - }; - - private int count; - - MessagePredicate getPredicate() { - return predicate; - } - - void setPredicate(MessagePredicate predicate) { - this.predicate = predicate; - } - - String getName() { - return name; - } - - void setName(String name) { - this.name = name; - } - - int getLimit() { - return limit; - } - - void setLimit(int limit) { - this.limit = limit; - } - - CounterListener getListener() { - return listener; - } - - void setListener(CounterListener listener) { - this.listener = listener; - } - - @Override - public void configure(Configuration config, ConfigurationContext context) { - predicate = (MessagePredicate) config.get("applyIf"); - limit = config.getInteger("limit"); - name = config.getString("name", "counter_" + ID.getAndIncrement()); - // TODO: - listener = System.out::println; - } - - @Override - public int filterInbound(Object req, Object resp, FlowContext context) { - if (predicate.test(req, resp, context)) { - if (++count >= limit) { - listener.limitReached(new CounterListener.Event(this)); - } - } - return DUNNO; - } - - @Override - public CounterFilter instanceForWorker(int index) { - CounterFilter filter = new CounterFilter(); - filter.predicate = predicate; - filter.name = name; - filter.limit = limit; - filter.listener = listener; - return filter; - } - - public static class NodeDefCreator implements NodeDefinitionCreator { - - @Override - public NodeDefinition create() { - return mapDef( - tupleDef("applyIf", new MessagePredicateNodeDefinition()), - tupleDef("limit", valueDefInteger()), - tupleDef("name", valueDef()).setRequired(false) - ); - } - - } -}
--- a/stress-tester/src/main/java/com/passus/st/client/filter/CounterListener.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -package com.passus.st.client.filter; - -/** - * - * @author mikolaj.podbielski - */ -public interface CounterListener { - - public void limitReached(Event event); - - public static final class Event { - private final CounterFilter filter; -// HttpRequest req - - public Event(CounterFilter filter) { - this.filter = filter; - } - - } -}
--- a/stress-tester/src/main/java/com/passus/st/client/filter/DefaultFlowFilterFactory.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.net.http.HttpMessage; -import com.passus.net.http.HttpRequest; -import com.passus.net.http.HttpResponse; -import com.passus.st.client.FlowContext; -import com.passus.st.client.http.HttpFlowConst; -import com.passus.st.client.http.HttpFlowContext; -import com.passus.st.client.http.filter.HttpFilterMessageWrapper; -import com.passus.st.client.http.filter.HttpFilterRequestWrapper; -import com.passus.st.client.http.filter.HttpFilterResponseWrapper; -import com.passus.st.client.http.filter.HttpMessageWrapper; - -import static com.passus.st.Protocols.HTTP; - -public final class DefaultFlowFilterFactory implements FlowFilterFactory { - - @Override - public MessageWrapper createWrapper(Object req, Object resp, FlowContext context) { - if (req instanceof HttpRequest || resp instanceof HttpResponse) { - return createHttpMessageWrapper((HttpRequest) req, (HttpResponse) resp, context); - } else { - return new MessageWrapper(req, resp, context); - } - } - - @Override - public MessageWrapper createWrapper(Object obj) { - if (obj instanceof HttpMessage) { - HttpMessage message = (HttpMessage) obj; - if (message.isRequest()) { - return createHttpMessageWrapper((HttpRequest) message, null, null); - } else { - return createHttpMessageWrapper(null, (HttpResponse) message, null); - } - } else { - return new MessageWrapper(obj, null, null); - } - } - - public HttpMessageWrapper createHttpMessageWrapper(HttpRequest req, HttpResponse resp, FlowContext context) { - HttpFilterRequestWrapper reqWrapper = (HttpFilterRequestWrapper) createHttpMessageWrapper(req); - HttpFilterResponseWrapper respWrapper = (HttpFilterResponseWrapper) createHttpMessageWrapper(resp); - - HttpFlowContext httpContext; - HttpFilterResponseWrapper origResp; - if (context != null) { - httpContext = context.getParamValue(HttpFlowConst.PARAM_HTTP_CONTEXT); - origResp = (HttpFilterResponseWrapper) createHttpMessageWrapper(httpContext.origResponse()); - } else { - httpContext = null; - origResp = null; - } - - return new HttpMessageWrapper(reqWrapper, respWrapper, context, origResp, httpContext); - } - - public HttpFilterMessageWrapper createHttpMessageWrapper(HttpMessage message) { - if (message == null) { - return null; - } - - if (message.isRequest()) { - return new HttpFilterRequestWrapper((HttpRequest) message); - } else { - return new HttpFilterResponseWrapper((HttpResponse) message); - } - } - -}
--- a/stress-tester/src/main/java/com/passus/st/client/filter/FilterDirection.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -package com.passus.st.client.filter; - -/** - * - * @author Mirosław Hawrot - */ -public enum FilterDirection { - - IN, OUT, BOTH - -}
--- a/stress-tester/src/main/java/com/passus/st/client/filter/FlowFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.config.Configurable; -import com.passus.config.Configuration; -import com.passus.config.ConfigurationContext; -import com.passus.st.client.FlowContext; - -public interface FlowFilter extends Configurable { - - int DENY = -1; - - int DUNNO = 0; - - int ACCEPT = 1; - - default void reset() { - - } - - @Override - default void configure(Configuration config, ConfigurationContext context) { - - } - - default int filterInbound(Object req, Object resp, FlowContext context) { - return DUNNO; - } - - default int filterOutbound(Object req, Object resp, FlowContext context) { - return DUNNO; - } - - FlowFilter instanceForWorker(int index); -}
--- a/stress-tester/src/main/java/com/passus/st/client/filter/FlowFilterChain.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.filter.Filter; -import com.passus.st.client.FlowContext; - -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -public class FlowFilterChain { - - protected final LinkedList<FlowFilter> filters = new LinkedList<>(); - - public List<FlowFilter> getFilters() { - return Collections.unmodifiableList(filters); - } - - @SuppressWarnings("unchecked") - public void addFilter(FlowFilter filter) { - filters.add(filter); - } - - public void clear() { - filters.clear(); - } - - public boolean isEmpty() { - return filters.isEmpty(); - } - - @SuppressWarnings("unchecked") - public int filterOutbound(Object request, Object resp, FlowContext context) { - Iterator<FlowFilter> it = filters.iterator(); - while (it.hasNext()) { - FlowFilter f = it.next(); - int res = f.filterOutbound(request, resp, context); - if (res != Filter.DUNNO) { - return res; - } - } - - return Filter.ACCEPT; - } - - @SuppressWarnings("unchecked") - public int filterInbound(Object request, Object resp, FlowContext context) { - Iterator<FlowFilter> it = filters.iterator(); - while (it.hasNext()) { - FlowFilter f = it.next(); - int res = f.filterInbound(request, resp, context); - if (res != Filter.DUNNO) { - return res; - } - } - - return Filter.ACCEPT; - } - - public void reset() { - Iterator<FlowFilter> it = filters.iterator(); - while (it.hasNext()) { - FlowFilter f = it.next(); - f.reset(); - } - } - - public FlowFilterChain instanceForWorker(int index) { - FlowFilterChain copy = new FlowFilterChain(); - - Iterator<FlowFilter> it = filters.iterator(); - while (it.hasNext()) { - FlowFilter f = it.next(); - copy.addFilter(f.instanceForWorker(index)); - } - - return copy; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("FlowFilterChain@").append(System.identityHashCode(this)); - sb.append(" {"); - - Iterator<FlowFilter> it = filters.iterator(); - while (it.hasNext()) { - FlowFilter f = it.next(); - sb.append(f).append(", "); - } - sb.append("}"); - - return sb.toString(); - } - -}
--- a/stress-tester/src/main/java/com/passus/st/client/filter/FlowFilterFactory.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.net.http.HttpRequest; -import com.passus.net.http.HttpResponse; -import com.passus.st.client.FlowContext; -import com.passus.st.client.http.filter.HttpMessageWrapper; - -public interface FlowFilterFactory { - - FlowFilterFactory DEFAULT_FACTORY = new DefaultFlowFilterFactory(); - - MessageWrapper createWrapper(Object req, Object resp, FlowContext context); - - MessageWrapper createWrapper(Object obj); - - HttpMessageWrapper createHttpMessageWrapper(HttpRequest req, HttpResponse resp, FlowContext context); - -}
--- a/stress-tester/src/main/java/com/passus/st/client/filter/FlowFilterNodeDefinitionCreator.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.config.schema.DynaKeyValueVaryListNodeDefinition; -import com.passus.config.schema.NodeDefinition; -import com.passus.config.schema.NodeDefinitionCreator; - -/** - * @author Mirosław Hawrot - */ -public class FlowFilterNodeDefinitionCreator implements NodeDefinitionCreator { - - public static NodeDefinition createFiltersList(boolean transformToObject) { - return new DynaKeyValueVaryListNodeDefinition("type", FlowFilterPluginFactory.getInstance()) - .setTransformToPluginObject(transformToObject); - } - - @Override - public NodeDefinition create() { - return createFiltersList(true); - } - -}
--- a/stress-tester/src/main/java/com/passus/st/client/filter/FlowFilterPluginFactory.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.commons.plugin.PluginFactory; -import com.passus.st.plugin.PluginConstants; - -/** - * @author Mirosław Hawrot - */ -public final class FlowFilterPluginFactory extends PluginFactory<FlowFilter> { - - private static FlowFilterPluginFactory instance; - - public FlowFilterPluginFactory() { - super(PluginConstants.CATEGORY_FLOW_FILTER, FlowFilter.class); - } - - public static synchronized FlowFilterPluginFactory getInstance() { - if (instance == null) { - instance = new FlowFilterPluginFactory(); - } - - return instance; - } -}
--- a/stress-tester/src/main/java/com/passus/st/client/filter/FlowFiltersConfigurator.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.commons.annotations.Plugin; -import com.passus.config.*; -import com.passus.config.schema.NodeDefinition; -import com.passus.config.validation.Errors; -import com.passus.st.plugin.PluginConstants; -import com.passus.st.utils.ConfigurationContextConsts; - -import java.io.File; -import java.io.IOException; -import java.util.List; - -/** - * @author Mirosław Hawrot - */ -@Plugin(name = FlowFiltersConfigurator.DOMAIN, category = PluginConstants.CATEGORY_DOMAIN_CONFIGURATOR) -public class FlowFiltersConfigurator implements DomainConfigurator { - - public static final String DOMAIN = "filters"; - - private static final FlowFilterNodeDefinitionCreator CREATOR = new FlowFilterNodeDefinitionCreator(); - - private final NodeDefinition nodeDef = CREATOR.create(); - - @Override - public String getDomain() { - return DOMAIN; - } - - public static List<FlowFilter> getFilters(File configFile, Errors errors, ConfigurationContext context) throws IOException, NodeException { - Configuration config = YamlConfigurationReader.readFromFile(configFile); - return getFilters(config, errors, context); - } - - public static List<FlowFilter> getFilters(String configStr, Errors errors, ConfigurationContext context) throws IOException, NodeException { - Configuration config = YamlConfigurationReader.readFromString(configStr); - return getFilters(config, errors, context); - } - - public static List<FlowFilter> getFilters(Configuration config, Errors errors, ConfigurationContext context) { - NodeDefinition nodeDef = CREATOR.create(); - return ConfigurationUtils.getDomainObjects(config, errors, context, DOMAIN, nodeDef); - } - - @Override - public void validate(Configuration config, Errors errors, ConfigurationContext context) { - CCompositeNode rootNode = config.getRootNode(); - nodeDef.validate(rootNode, errors, context); - } - - @Override - public void configure(Configuration config, Errors errors, ConfigurationContext context) { - CCompositeNode rootNode = config.getRootNode(); - nodeDef.transform(rootNode, errors, context); - if (!errors.hasError()) { - try { - List<FlowFilter> filters = ConfigurationUtils.convertToList(rootNode, FlowFilter.class); - context.add(ConfigurationContextConsts.FLOW_FILTERS, filters); - } catch (Exception e) { - throw new RuntimeException(e.getMessage(), e); - } - - } - } - -}
--- a/stress-tester/src/main/java/com/passus/st/client/filter/MatchFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.commons.Assert; -import com.passus.commons.annotations.Plugin; -import com.passus.config.Configuration; -import com.passus.config.ConfigurationContext; -import com.passus.config.annotations.NodeDefinitionCreate; -import com.passus.config.schema.NodeDefinition; -import com.passus.config.schema.NodeDefinitionCreator; -import com.passus.st.client.FlowContext; -import com.passus.st.plugin.PluginConstants; - -import static com.passus.config.schema.ConfigurationSchemaBuilder.*; - -/** - * @author Mirosław Hawrot - */ -@NodeDefinitionCreate(MatchFilter.MatchFilterNodeDefCreator.class) -@Plugin(name = MatchFilter.TYPE, category = PluginConstants.CATEGORY_FLOW_FILTER) -public class MatchFilter implements FlowFilter { - - public static final String TYPE = "matcher"; - - private MessagePredicate predicate; - - private boolean acceptOnMatch = true; - - private final FlowFilterFactory filterFactory; - - public MatchFilter() { - this(FlowFilterFactory.DEFAULT_FACTORY); - } - - public MatchFilter(FlowFilterFactory filterFactory) { - Assert.notNull(filterFactory, "filterFactory"); - this.filterFactory = filterFactory; - } - - public MessagePredicate getPredicate() { - return predicate; - } - - public void setPredicate(MessagePredicate predicate) { - this.predicate = predicate; - } - - public boolean isAcceptOnMatch() { - return acceptOnMatch; - } - - public void setAcceptOnMatch(boolean acceptOnMatch) { - this.acceptOnMatch = acceptOnMatch; - } - - @Override - public void configure(Configuration config, ConfigurationContext context) { - predicate = (MessagePredicate) config.get("matches"); - acceptOnMatch = config.getBoolean("acceptOnMatch", true); - } - - @Override - public int filterOutbound(Object request, Object resp, FlowContext context) { - if (predicate == null) { - return DUNNO; - } - - boolean match = predicate.test(filterFactory.createWrapper(request, resp, context)); - if (!match) { - return DUNNO; - } - - return acceptOnMatch ? ACCEPT : DENY; - } - - @Override - public MatchFilter instanceForWorker(int index) { - MatchFilter filter = new MatchFilter(); - filter.acceptOnMatch = acceptOnMatch; - filter.predicate = predicate; - return filter; - } - - public static class MatchFilterNodeDefCreator implements NodeDefinitionCreator { - - @Override - public NodeDefinition create() { - return mapDef( - tupleDef("acceptOnMatch", valueDefBool()).setRequired(false), - tupleDef("matches", new MessagePredicateNodeDefinition()) - ); - } - - } -}
--- a/stress-tester/src/main/java/com/passus/st/client/filter/MessagePredicate.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.commons.Assert; -import com.passus.commons.ConversionException; -import com.passus.config.NodeException; -import com.passus.st.client.FlowContext; -import com.passus.st.filter.Transformers; - -import java.io.IOException; -import java.util.function.Predicate; - -import static com.passus.st.client.filter.FlowFilterFactory.DEFAULT_FACTORY; - -public class MessagePredicate<T> implements Predicate<T> { - - protected final Predicate predicate; - - protected final FlowFilterFactory filterFactory; - - public MessagePredicate(Predicate predicate) { - this(predicate, DEFAULT_FACTORY); - } - - public MessagePredicate(Predicate predicate, FlowFilterFactory filterFactory) { - Assert.notNull(predicate, "predicate"); - Assert.notNull(filterFactory, "filterFactory"); - this.predicate = predicate; - this.filterFactory = filterFactory; - } - - public Predicate getPredicate() { - return predicate; - } - - public boolean test(Object req, Object resp, FlowContext context) { - return test(filterFactory.createWrapper(req, resp, context)); - } - - public boolean test(MessageWrapper wrapper) { - return predicate.test(wrapper); - } - - @Override - public boolean test(T message) { - return predicate.test(filterFactory.createWrapper(message)); - } - - @Override - public String toString() { - return predicate.toString(); - } - - public static MessagePredicate parse(String content) throws ConversionException, IOException, NodeException { - Predicate predicate = Transformers.PREDICATE.transform(content); - return new MessagePredicate(predicate); - } -}
--- a/stress-tester/src/main/java/com/passus/st/client/filter/MessagePredicateNodeDefinition.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.commons.ConversionException; -import com.passus.commons.utils.ArrayUtils; -import com.passus.config.*; -import com.passus.config.schema.NodeDefinition; -import com.passus.config.validation.Errors; -import com.passus.filter.config.PredicateNodeTransformer; -import com.passus.lookup.filter.LookupKeyExistsLeftOperatorTransformer; -import com.passus.lookup.filter.LookupValueExtractorTransformer; -import com.passus.st.filter.Transformers; - -import java.util.Set; -import java.util.function.Predicate; - -import static com.passus.config.validation.ValidationDefaultMessages.GENERAL_CONVERSION_ERROR; - -/** - * @author Mirosław Hawrot - */ -public class MessagePredicateNodeDefinition extends NodeDefinition<MessagePredicateNodeDefinition> { - - private static final PredicateNodeTransformer TRANSFORMER = Transformers.PREDICATE; - - private final static Set<Class<? extends CNode>> SUPPORTED = ArrayUtils.asUnmodifiableSet(CListNode.class, CMapNode.class); - - @Override - public Set<Class<? extends CNode>> getSupportedNode() { - return SUPPORTED; - } - - @Override - protected void doValidate(CNode node, Errors errors, ConfigurationContext context) { - try { - // TODO: refactor - LookupKeyExistsLeftOperatorTransformer lookupKeyExistsTransformer = Transformers.lookupKeyExistsTransformer(context); - LookupValueExtractorTransformer lookupValueTransformer = Transformers.lookupValueTransformer(context); - TRANSFORMER.addLeftOperatorTransformer(lookupKeyExistsTransformer); - TRANSFORMER.addValueExtractorTransformer(lookupValueTransformer); - TRANSFORMER.transform(node); - TRANSFORMER.removeLeftOperatorTransformer(lookupKeyExistsTransformer); - TRANSFORMER.removeValueExtractorTransformer(lookupValueTransformer); - } catch (NodeConversionException ex) { - errors.reject(node, ex.getMessage()); - } catch (ConversionException ex) { - errors.reject(node, GENERAL_CONVERSION_ERROR); - } - } - - @Override - protected CNode doTransform(CNode node, Errors errors, ConfigurationContext context, boolean reverse) { - if (reverse) { - throw new UnsupportedOperationException("Not supported yet."); - } else { - try { - // TODO: refactor - LookupKeyExistsLeftOperatorTransformer lookupKeyExistsTransformer = Transformers.lookupKeyExistsTransformer(context); - LookupValueExtractorTransformer lookupValueTransformer = Transformers.lookupValueTransformer(context); - TRANSFORMER.addLeftOperatorTransformer(lookupKeyExistsTransformer); - TRANSFORMER.addValueExtractorTransformer(lookupValueTransformer); - Predicate predicate = TRANSFORMER.transform(node); - TRANSFORMER.removeLeftOperatorTransformer(lookupKeyExistsTransformer); - TRANSFORMER.removeValueExtractorTransformer(lookupValueTransformer); - return new CValueNode(new MessagePredicate(predicate)); - } catch (NodeConversionException ex) { - errors.reject(node, ex.getMessage()); - } catch (ConversionException ex) { - errors.reject(node, GENERAL_CONVERSION_ERROR); - } - } - - return null; - } - - @Override - protected boolean doEquals(CNode node1, CNode node2) { - throw new UnsupportedOperationException("Not supported yet."); - } - -}
--- a/stress-tester/src/main/java/com/passus/st/client/filter/MessageWrapper.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.st.client.FlowContext; - -public class MessageWrapper<R, S> { - - protected final R req; - - protected final S resp; - - protected final FlowContext context; - - public MessageWrapper(R req, S resp, FlowContext context) { - this.req = req; - this.resp = resp; - this.context = context; - } - - public R getReq() { - return req; - } - - public S getResp() { - return resp; - } - -}
--- a/stress-tester/src/main/java/com/passus/st/client/filter/MvelFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.commons.Assert; -import com.passus.commons.annotations.Plugin; -import com.passus.config.Configuration; -import com.passus.config.ConfigurationContext; -import com.passus.config.annotations.NodeDefinitionCreate; -import com.passus.config.schema.NodeDefinition; -import com.passus.config.schema.NodeDefinitionCreator; -import com.passus.net.http.HttpRequest; -import com.passus.st.client.FlowContext; -import com.passus.st.client.http.HttpScopes; -import com.passus.st.client.http.filter.HttpFilter; -import com.passus.st.config.StringSourceNodeDefinition; -import com.passus.st.config.StringToExecutableStatementValueTransformer; -import com.passus.st.plugin.PluginConstants; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.mvel2.compiler.ExecutableStatement; -import org.mvel2.integration.VariableResolverFactory; -import org.mvel2.integration.impl.CachingMapVariableResolverFactory; - -import java.util.HashMap; -import java.util.Map; - -import static com.passus.config.schema.ConfigurationSchemaBuilder.*; -import static com.passus.st.client.http.filter.HttpFlowUtils.extractHttpContext; - -/** - * @author Mirosław Hawrot - */ -@NodeDefinitionCreate(MvelFilter.MvelFilterNodeDefCreator.class) -@Plugin(name = MvelFilter.TYPE, category = PluginConstants.CATEGORY_FLOW_FILTER) -public class MvelFilter implements FlowFilter { - - public static final String TYPE = "mvel"; - - private static final Logger LOGGER = LogManager.getLogger(MvelFilter.class); - - private VariableResolverFactory globalFactory; - - private ExecutableStatement statement; - - private FilterDirection direction = FilterDirection.OUT; - - public MvelFilter() { - } - - public MvelFilter(ExecutableStatement statement, FilterDirection direction) { - Assert.notNull(statement, "statement"); - Assert.notNull(direction, "direction"); - this.statement = statement; - this.direction = direction; - } - - public VariableResolverFactory getGlobalFactory() { - return globalFactory; - } - - public void setGlobalFactory(VariableResolverFactory globalFactory) { - this.globalFactory = globalFactory; - } - - public FilterDirection getDirection() { - return direction; - } - - public void setDirection(FilterDirection direction) { - Assert.notNull(direction, "direction"); - this.direction = direction; - } - - public ExecutableStatement getStatement() { - return statement; - } - - public void setStatement(ExecutableStatement statement) { - this.statement = statement; - } - - @Override - public void configure(Configuration config, ConfigurationContext context) { - direction = config.get("dir", FilterDirection.OUT); - statement = (ExecutableStatement) config.get("script"); - } - - private int filter(Object req, Object resp, FlowContext context) { - if (statement == null) { - return DUNNO; - } - - Map<String, Object> vars = new HashMap<>(3); - vars.put("$req", req); - vars.put("$resp", resp); - vars.put("$context", context); - if (context != null && req instanceof HttpRequest) { - HttpRequest httpReq = (HttpRequest) req; - HttpScopes scopes = extractHttpContext(context).scopes(); - vars.put("$extractHttpContext", scopes); - vars.put("$httpSession", scopes.getSession(httpReq)); - } - - CachingMapVariableResolverFactory factory = new CachingMapVariableResolverFactory(vars); - if (globalFactory != null) { - factory.setNextFactory(globalFactory); - } - - try { - Object out = statement.getValue(null, factory); - if (out instanceof Integer) { - int value = (Integer) out; - if (value < 0) { - return DENY; - } else if (value > 0) { - return ACCEPT; - } - - return DUNNO; - } - } catch (Throwable th) { - LOGGER.trace(th); - } - - return DUNNO; - } - - @Override - public int filterOutbound(Object req, Object resp, FlowContext context) { - if (direction == FilterDirection.BOTH || direction == FilterDirection.OUT) { - return filter(req, resp, context); - } - - return DUNNO; - } - - @Override - public int filterInbound(Object req, Object resp, FlowContext context) { - if (direction == FilterDirection.BOTH || direction == FilterDirection.IN) { - return filter(req, resp, context); - } - - return DUNNO; - } - - @Override - public FlowFilter instanceForWorker(int index) { - throw new UnsupportedOperationException("Not supported yet."); - } - - public static final class MvelFilterNodeDefCreator implements NodeDefinitionCreator { - - @Override - public NodeDefinition create() { - return mapDef( - tupleDef("dir", enumDef(FilterDirection.class)).setRequired(false), - tupleDef("script", new StringSourceNodeDefinition() - .setTransformer(new StringToExecutableStatementValueTransformer()) - ) - ); - } - - } -}
--- a/stress-tester/src/main/java/com/passus/st/client/filter/SequenceFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,482 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.commons.Assert; -import com.passus.commons.annotations.Plugin; -import com.passus.commons.metric.MapMetric; -import com.passus.commons.service.Registry; -import com.passus.commons.time.SystemTimeGenerator; -import com.passus.commons.time.TimeAware; -import com.passus.commons.time.TimeGenerator; -import com.passus.config.*; -import com.passus.config.annotations.NodeDefinitionCreate; -import com.passus.config.schema.*; -import com.passus.config.validation.Errors; -import com.passus.filter.ValueExtractor; -import com.passus.filter.ValueExtractorParser; -import com.passus.filter.config.PredicateNodeTransformer; -import com.passus.st.client.FlowContext; -import com.passus.st.client.http.ReporterDestination; -import com.passus.st.filter.Transformers; -import com.passus.st.plugin.PluginConstants; - -import java.io.Serializable; -import java.text.ParseException; -import java.util.*; -import java.util.function.Predicate; - -import static com.passus.config.schema.ConfigurationSchemaBuilder.*; - -/** - * @author mikolaj.podbielski - */ -@NodeDefinitionCreate(SequenceFilter.NodeDefCreator.class) -@Plugin(name = SequenceFilter.TYPE, category = PluginConstants.CATEGORY_FLOW_FILTER) -public class SequenceFilter implements FlowFilter, TimeAware { - - public static class SequenceItem { - - private final Predicate predicate; - private boolean mustOccur = true; - private long time = 10_000; - private int num; - private String alias; - private String[] aliases; - - public SequenceItem(Predicate predicate, int num) { - this(predicate); - this.num = num; - } - - public SequenceItem(Predicate predicate) { - if (predicate == null) { - throw new NullPointerException(); - } - this.predicate = predicate; - } - - public Predicate getPredicate() { - return predicate; - } - - public int getNum() { - return num; - } - - public void setNum(int num) { - this.num = num; - } - - public long getTime() { - return time; - } - - public void setTime(long time) { - if (time <= 0) { - throw new IllegalArgumentException("Time must be greater than zero."); - } - this.time = time; - } - - public String getAlias() { - return alias; - } - - public void setAlias(String alias) { - this.alias = alias; - aliases = null; - } - - public boolean isMustOccur() { - return mustOccur; - } - - public void setMustOccur(boolean mustOccur) { - this.mustOccur = mustOccur; - } - - private boolean match(Map<String, Object> value) { - return predicate.test(value); - } - - private String[] getAliases() { - if (aliases == null) { - if (alias != null) { - aliases = new String[2]; - aliases[1] = alias; - } else { - aliases = new String[1]; - } - - aliases[0] = "_i" + num; - } - - return aliases; - } - } - - private static class SeqChainItem { - - private final SequenceItem seq; - private SeqChainItem next; - private final long startTime; - private final long endTime; - private boolean active = true; - - public SeqChainItem(SequenceItem seq, long startTime) { - this.seq = seq; - this.startTime = startTime; - this.endTime = startTime + seq.time; - } - - public void setNext(SeqChainItem next) { - this.next = next; - } - - public long getStartTime() { - return startTime; - } - - public long getEndTime() { - return endTime; - } - - public boolean match(Map<String, Object> value) { - return seq.match(value); - } - - public SeqChainItem getNext() { - return next; - } - - public boolean inTimeRange(long time) { - return (startTime <= time && time < endTime); - } - } - - private static class SeqChain { - - private SeqChainItem seqItem; - - private final Map<String, Object> valueMap; -// private Filterable value = new FilterableMap(); -// private FlowMarker flowMarker; - - public SeqChain(SequenceItem[] seqItems, long startTime, Map<String, Object> valueMap) { - this.valueMap = valueMap; - - SeqChainItem curItem = new SeqChainItem(seqItems[1], startTime); - seqItem = curItem; - - for (int i = 2; i < seqItems.length; i++) { - SeqChainItem nexItem = new SeqChainItem(seqItems[i], curItem.getStartTime()); - curItem.setNext(nexItem); - curItem = nexItem; - } - } - - public void updateValue(MessageWrapper wrapper) { - valueMap.put("req", wrapper.getReq()); - valueMap.put("resp", wrapper.getResp()); - } - - public void persistsValue(MessageWrapper wrapper, String[] aliases) { - for (String alias : aliases) { - valueMap.put(alias, wrapper); - } - } - - public boolean hasNext() { - return (seqItem != null && seqItem.getNext() != null); - } - - public boolean next() { - if (seqItem == null) { - return false; - } - - seqItem = seqItem.getNext(); - return true; - } - - public boolean rewind(long time) { - if (seqItem == null) { - return false; - } - - while (hasNext()) { - if (seqItem.inTimeRange(time)) { - return true; - } else if (seqItem.seq.mustOccur) { - return false; - } - - next(); - } - - return false; - } - } - - public static final String TYPE = "sequence"; - - private final List<SeqChain> chains = new ArrayList<>(); - private SequenceListener listener = (e) -> { - }; - private SequenceItem[] seqItems; - private Map<String, ValueExtractor> values = Collections.EMPTY_MAP; - - private final FlowFilterFactory filterFactory; - - private TimeGenerator timeGenerator = new SystemTimeGenerator(); - - public SequenceFilter() { - this(FlowFilterFactory.DEFAULT_FACTORY); - } - - public SequenceFilter(FlowFilterFactory filterFactory) { - Assert.notNull(filterFactory, "filterFactory"); - this.filterFactory = filterFactory; - } - - public SequenceListener getListener() { - return listener; - } - - public void setListener(SequenceListener listener) { - this.listener = listener; - } - - public SequenceItem[] getSeqItems() { - return seqItems; - } - - public void setSeqItems(SequenceItem[] seqItems) { - this.seqItems = seqItems; - } - - public Map<String, ValueExtractor> getValues() { - return values; - } - - public void setValues(Map<String, ValueExtractor> values) { - this.values = values; - } - - @Override - public TimeGenerator getTimeGenerator() { - return timeGenerator; - } - - @Override - public void setTimeGenerator(TimeGenerator timeGenerator) { - Assert.notNull(timeGenerator, "timeGenerator"); - this.timeGenerator = timeGenerator; - } - - private void processValue(long now, MessageWrapper value) { - Iterator<SeqChain> iterator = chains.iterator(); - while (iterator.hasNext()) { - SeqChain chain = iterator.next(); - - if (chain.seqItem.startTime <= now) { - if (!chain.seqItem.inTimeRange(now) && !chain.rewind(now)) { - chain.persistsValue(value, chain.seqItem.seq.getAliases()); - fireEvent(chain); - iterator.remove(); - } else if (chain.seqItem.active) { - chain.updateValue(value); - - if (chain.seqItem.match(chain.valueMap)) { - if (!chain.seqItem.seq.mustOccur) { - iterator.remove(); - } else { - chain.persistsValue(value, chain.seqItem.seq.getAliases()); - if (!chain.hasNext()) { - fireEvent(chain); - iterator.remove(); - } else if (!chain.next()) { - fireEvent(chain); - iterator.remove(); - } - } - } - } - } - } - - final Map<String, Object> valueMap = new HashMap<>(); - valueMap.put("req", value.getReq()); - valueMap.put("resp", value.getResp()); - - if (seqItems[0].match(valueMap)) { - SeqChain chain = new SeqChain(seqItems, now, valueMap); - chain.persistsValue(value, seqItems[0].getAliases()); - chains.add(chain); - } - } - - private void fireEvent(SeqChain chain) { - Map<String, Serializable> result; - - if (values.isEmpty()) { - result = Collections.emptyMap(); - } else { - result = new HashMap<>(); - Map<String, Object> persisted = chain.valueMap; - for (Map.Entry<String, ValueExtractor> e : values.entrySet()) { - Object value = e.getValue().extract(persisted); - if (value instanceof Serializable) { - result.put(e.getKey(), (Serializable) value); - } - } - } - - listener.sequenceDetected(new MapMetric("sequence", result)); - } - - @Override - public int filterInbound(Object req, Object resp, FlowContext context) { - MessageWrapper wrapper = filterFactory.createWrapper(req, resp, context); - processValue(timeGenerator.currentTimeMillis(), wrapper); - return DUNNO; - } - - @Override - public void reset() { - chains.clear(); - } - - @Override - public SequenceFilter instanceForWorker(int index) { - SequenceFilter filter = new SequenceFilter(); - filter.listener = listener; - filter.seqItems = seqItems; - filter.values = values; - return filter; - } - - @Override - public void configure(Configuration config, ConfigurationContext context) { - List<SequenceItem> itemsList = (List<SequenceItem>) config.get("sequence"); - seqItems = itemsList.toArray(new SequenceItem[itemsList.size()]); - for (int i = 0; i < seqItems.length; ++i) { - seqItems[i].setNum(i); - } - - values = (Map<String, ValueExtractor>) config.get("values", Collections.EMPTY_MAP); - ReporterDestination reporterDestination = Registry.getInstance().get( - ReporterDestination.SERVICE_NAME, ReporterDestination.class); - if (reporterDestination != null) { - listener = reporterDestination; - } - } - - public static class NodeDefCreator implements NodeDefinitionCreator { - - @Override - public NodeDefinition create() { - MapNodeDefinition elementDef = mapDef( - tupleDef("match", new MessagePredicateNodeDefinition()), - tupleDef("mustOccur", valueDef(Boolean.class)).setRequired(false), - tupleDef("time", valueDef(Long.class)).setRequired(false), - tupleDef("alias", valueDef()).setRequired(false) - ); - elementDef.setTransformer(new SequencesNodeTransformer()); - // TODO: mustOccur and time required in all steps but first - - return mapDef( - tupleDef("sequence", new ListNodeDefinition(elementDef).setMinNumberOfValues(2)), - tupleDef("values", new MappingNodeDefinition().setTransformer(new ValuesNodeTransformer())).setRequired(false) - ); - } - - } - - private static class SequencesNodeTransformer implements NodeTransformer<CNode> { - - private static final PredicateNodeTransformer TRANSFORMER = Transformers.PREDICATE; - - @Override - public CNode transform(CNode node, Errors errors, ConfigurationContext context) { - try { - CMapNode mapNode = (CMapNode) node; - List<CTupleNode> tupleNodes = mapNode.getChildren(); - - Predicate predicate = null; - boolean mustOccur = true; - long time = 0; - String alias = null; - for (CTupleNode tupleNode : tupleNodes) { - String name = tupleNode.getName(); - CNode valueNode = tupleNode.getNode(); - switch (name) { - case "match": - predicate = TRANSFORMER.transform(valueNode); - break; - case "mustOccur": - mustOccur = (Boolean) getValue(valueNode); - break; - case "time": - time = (Long) getValue(valueNode); - break; - case "alias": - alias = (String) getValue(valueNode); - break; - } - } - SequenceItem item = new SequenceItem(predicate); - if (time > 0) { - item.setTime(time); - } - item.setMustOccur(mustOccur); - item.setAlias(alias); - return new CValueNode(item); - } catch (Exception ex) { - return node; - } - } - - @Override - public CNode reverseTransform(CNode node, Errors errors, ConfigurationContext context) { - throw new UnsupportedOperationException("Not supported yet."); - } - - } - - private static class ValuesNodeTransformer implements NodeTransformer<CNode> { - - @Override - public CNode transform(CNode node, Errors errors, ConfigurationContext context) { - Map<String, ValueExtractor> result = new HashMap<>(); - - CMapNode mapNode = (CMapNode) node; - List<CTupleNode> tupleNodes = mapNode.getChildren(); - for (CTupleNode tupleNode : tupleNodes) { - String name = tupleNode.getName(); - CValueNode valueNode = (CValueNode) tupleNode.getNode(); - String value = (String) valueNode.getValue(); - try { - errors.pushNestedPath(name); - ValueExtractor extractor = ValueExtractorParser.DEFAULT.parse(value); - result.put(name, extractor); - } catch (ParseException ex) { - errors.reject(tupleNode, "Invalid expression: \"%s\"", value); - } finally { - errors.popNestedPath(); - } - } - return new CValueNode(result); - } - - @Override - public CNode reverseTransform(CNode node, Errors errors, ConfigurationContext context) { - throw new UnsupportedOperationException("Impossible."); // ValueExtractor - } - - } - - private static Object getValue(CNode node) { - CValueNode valueNode = (CValueNode) node; - return valueNode.getValue(); - } -}
--- a/stress-tester/src/main/java/com/passus/st/client/filter/SequenceListener.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.commons.metric.MapMetric; - -/** - * - * @author mikolaj.podbielski - */ -public interface SequenceListener { - - void sequenceDetected(MapMetric sequence); -}
--- a/stress-tester/src/main/java/com/passus/st/client/http/ReporterDestination.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/http/ReporterDestination.java Thu Mar 26 13:27:52 2020 +0100 @@ -9,7 +9,7 @@ import com.passus.net.http.HttpMessage; import com.passus.st.client.ClientListener; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.SequenceListener; +import com.passus.st.filter.SequenceListener; import com.passus.st.metric.MetricsCollectionHandler; import java.util.Arrays;
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpAbstractLoginFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpAbstractLoginFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -17,9 +17,9 @@ import com.passus.st.client.credentials.CredentialsProvider.ProviderContext; import com.passus.st.client.credentials.CredentialsProviderFactory; import com.passus.st.client.credentials.MultiCredentialsProviderTransformer; -import com.passus.st.client.filter.FlowFilterFactory; -import com.passus.st.client.filter.MessagePredicate; -import com.passus.st.client.filter.MessagePredicateNodeDefinition; +import com.passus.st.filter.FlowFilterFactory; +import com.passus.st.filter.MessagePredicate; +import com.passus.st.filter.MessagePredicateNodeDefinition; import java.util.Collection;
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpBasicAuthLoginFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpBasicAuthLoginFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -16,7 +16,7 @@ import static com.passus.st.client.http.HttpConsts.PARAM_USERNAME; import static com.passus.st.client.http.filter.HttpFlowUtils.extractHttpContext; -import com.passus.st.client.filter.MessagePredicate; +import com.passus.st.filter.MessagePredicate; import com.passus.st.client.http.HttpScopes; import com.passus.st.plugin.PluginConstants; import java.nio.charset.Charset;
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpDigestAuthLoginFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpDigestAuthLoginFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -20,7 +20,7 @@ import static com.passus.st.client.http.HttpConsts.PARAM_USERNAME; import static com.passus.st.client.http.filter.HttpFlowUtils.extractHttpContext; -import com.passus.st.client.filter.MessagePredicate; +import com.passus.st.filter.MessagePredicate; import com.passus.st.client.http.HttpFlowContext; import com.passus.st.plugin.PluginConstants; import java.util.HashMap;
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -3,7 +3,7 @@ import com.passus.net.http.HttpRequest; import com.passus.net.http.HttpResponse; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FlowFilter; +import com.passus.st.filter.FlowFilter; /** * @author Mirosław Hawrot
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpFiltersUtils.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpFiltersUtils.java Thu Mar 26 13:27:52 2020 +0100 @@ -5,9 +5,8 @@ import com.passus.net.http.HttpRequest; import com.passus.net.http.HttpResponse; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FlowFilterFactory; -import com.passus.st.client.filter.MessageWrapper; -import com.passus.st.client.http.HttpFlowContext; +import com.passus.st.filter.FlowFilterFactory; +import com.passus.st.filter.MessageWrapper; /** *
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpFormLoginFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpFormLoginFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -11,7 +11,7 @@ import com.passus.st.client.credentials.Credentials; import com.passus.st.client.credentials.CredentialsProvider; import com.passus.st.client.credentials.CredentialsProvider.ProviderContext; -import com.passus.st.client.filter.MessagePredicate; +import com.passus.st.filter.MessagePredicate; import com.passus.st.client.http.HttpScopes; import com.passus.st.plugin.PluginConstants; import org.apache.logging.log4j.LogManager;
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpLogoutFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpLogoutFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -10,8 +10,8 @@ import com.passus.net.http.HttpResponse; import com.passus.st.ParametersBag; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.MessagePredicate; -import com.passus.st.client.filter.MessagePredicateNodeDefinition; +import com.passus.st.filter.MessagePredicate; +import com.passus.st.filter.MessagePredicateNodeDefinition; import com.passus.st.client.http.HttpScopes; import com.passus.st.plugin.PluginConstants;
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpMarkFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpMarkFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -13,9 +13,9 @@ import com.passus.net.http.HttpRequest; import com.passus.net.http.HttpResponse; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.MessagePredicate; -import com.passus.st.client.filter.MessagePredicateNodeDefinition; -import com.passus.st.client.filter.MessageWrapper; +import com.passus.st.filter.MessagePredicate; +import com.passus.st.filter.MessagePredicateNodeDefinition; +import com.passus.st.filter.MessageWrapper; import com.passus.st.filter.Transformers; import com.passus.st.plugin.PluginConstants;
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpMessageModificationFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpMessageModificationFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -11,10 +11,10 @@ import com.passus.net.http.HttpRequest; import com.passus.net.http.HttpResponse; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.*; import com.passus.st.client.http.filter.HttpMessageModificationOperations.Operation; import com.passus.st.config.FieldValueExtractorTransformerNodeDefCreator; import com.passus.st.config.HeaderOperationNodeDefinition; +import com.passus.st.filter.*; import com.passus.st.plugin.PluginConstants; import com.passus.st.validation.HttpValidators; import org.apache.logging.log4j.LogManager;
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpMessageModificationOperations.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpMessageModificationOperations.java Thu Mar 26 13:27:52 2020 +0100 @@ -6,7 +6,7 @@ import com.passus.filter.ValueExtractor; import com.passus.net.http.*; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FlowFilterFactory; +import com.passus.st.filter.FlowFilterFactory; import com.passus.st.extractor.ContentReplacer; import com.passus.st.extractor.RegexValueExtractor; import org.apache.logging.log4j.LogManager;
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpMessageWrapper.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpMessageWrapper.java Thu Mar 26 13:27:52 2020 +0100 @@ -5,7 +5,7 @@ import com.passus.net.http.HttpResponse; import com.passus.st.ParametersBag; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.MessageWrapper; +import com.passus.st.filter.MessageWrapper; import com.passus.st.client.http.HttpFlowContext; import com.passus.st.client.http.HttpScopes; import com.passus.st.emitter.SessionInfo;
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpScopeModificationFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpScopeModificationFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -13,9 +13,9 @@ import com.passus.net.http.HttpResponse; import com.passus.st.ParametersBag; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.*; import com.passus.st.config.FieldValueExtractorTransformerNodeDefCreator; import com.passus.st.config.HeaderOperationNodeDefinition; +import com.passus.st.filter.*; import com.passus.st.plugin.PluginConstants; import java.util.ArrayList;
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpVarsFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpVarsFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -9,7 +9,7 @@ import com.passus.net.http.HttpRequest; import com.passus.net.http.HttpResponse; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FlowFilterFactory; +import com.passus.st.filter.FlowFilterFactory; import com.passus.st.vars.Var; import com.passus.st.vars.VarsCompiler; import com.passus.st.vars.VarsExecutor;
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpZoneFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpZoneFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -12,8 +12,8 @@ import com.passus.net.http.HttpRequest; import com.passus.net.http.HttpResponse; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FlowFilterFactory; -import com.passus.st.client.filter.MessagePredicate; +import com.passus.st.filter.FlowFilterFactory; +import com.passus.st.filter.MessagePredicate; import com.passus.st.filter.Transformers; import com.passus.st.plugin.PluginConstants;
--- a/stress-tester/src/main/java/com/passus/st/client/netflow/filter/NetflowFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/netflow/filter/NetflowFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -2,7 +2,7 @@ import com.passus.net.netflow.Netflow; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FlowFilter; +import com.passus.st.filter.FlowFilter; public abstract class NetflowFilter implements FlowFilter {
--- a/stress-tester/src/main/java/com/passus/st/client/netflow/filter/NetflowVersionFilter.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/client/netflow/filter/NetflowVersionFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -9,7 +9,7 @@ import com.passus.config.schema.NodeDefinitionCreator; import com.passus.net.netflow.Netflow; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FlowFilter; +import com.passus.st.filter.FlowFilter; import com.passus.st.plugin.PluginConstants; import java.util.HashSet;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/CounterFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,109 @@ +package com.passus.st.filter; + +import com.passus.commons.annotations.Plugin; +import com.passus.config.Configuration; +import com.passus.config.ConfigurationContext; +import com.passus.config.annotations.NodeDefinitionCreate; +import com.passus.config.schema.NodeDefinition; +import com.passus.config.schema.NodeDefinitionCreator; +import com.passus.st.client.FlowContext; +import com.passus.st.plugin.PluginConstants; + +import java.util.concurrent.atomic.AtomicInteger; + +import static com.passus.config.schema.ConfigurationSchemaBuilder.*; + +/** + * + * @author mikolaj.podbielski + */ +@NodeDefinitionCreate(CounterFilter.NodeDefCreator.class) +@Plugin(name = CounterFilter.TYPE, category = PluginConstants.CATEGORY_FLOW_FILTER) +public class CounterFilter implements FlowFilter { + + public static final String TYPE = "counter"; + + private static final AtomicInteger ID = new AtomicInteger(); + + private MessagePredicate predicate; + private String name; + private int limit; + private CounterListener listener = (e) -> { + }; + + private int count; + + MessagePredicate getPredicate() { + return predicate; + } + + void setPredicate(MessagePredicate predicate) { + this.predicate = predicate; + } + + String getName() { + return name; + } + + void setName(String name) { + this.name = name; + } + + int getLimit() { + return limit; + } + + void setLimit(int limit) { + this.limit = limit; + } + + CounterListener getListener() { + return listener; + } + + void setListener(CounterListener listener) { + this.listener = listener; + } + + @Override + public void configure(Configuration config, ConfigurationContext context) { + predicate = (MessagePredicate) config.get("applyIf"); + limit = config.getInteger("limit"); + name = config.getString("name", "counter_" + ID.getAndIncrement()); + // TODO: + listener = System.out::println; + } + + @Override + public int filterInbound(Object req, Object resp, FlowContext context) { + if (predicate.test(req, resp, context)) { + if (++count >= limit) { + listener.limitReached(new CounterListener.Event(this)); + } + } + return DUNNO; + } + + @Override + public CounterFilter instanceForWorker(int index) { + CounterFilter filter = new CounterFilter(); + filter.predicate = predicate; + filter.name = name; + filter.limit = limit; + filter.listener = listener; + return filter; + } + + public static class NodeDefCreator implements NodeDefinitionCreator { + + @Override + public NodeDefinition create() { + return mapDef( + tupleDef("applyIf", new MessagePredicateNodeDefinition()), + tupleDef("limit", valueDefInteger()), + tupleDef("name", valueDef()).setRequired(false) + ); + } + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/CounterListener.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,20 @@ +package com.passus.st.filter; + +/** + * + * @author mikolaj.podbielski + */ +public interface CounterListener { + + public void limitReached(Event event); + + public static final class Event { + private final CounterFilter filter; +// HttpRequest req + + public Event(CounterFilter filter) { + this.filter = filter; + } + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/DefaultFlowFilterFactory.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,68 @@ +package com.passus.st.filter; + +import com.passus.net.http.HttpMessage; +import com.passus.net.http.HttpRequest; +import com.passus.net.http.HttpResponse; +import com.passus.st.client.FlowContext; +import com.passus.st.client.http.HttpFlowConst; +import com.passus.st.client.http.HttpFlowContext; +import com.passus.st.client.http.filter.HttpFilterMessageWrapper; +import com.passus.st.client.http.filter.HttpFilterRequestWrapper; +import com.passus.st.client.http.filter.HttpFilterResponseWrapper; +import com.passus.st.client.http.filter.HttpMessageWrapper; + +public final class DefaultFlowFilterFactory implements FlowFilterFactory { + + @Override + public MessageWrapper createWrapper(Object req, Object resp, FlowContext context) { + if (req instanceof HttpRequest || resp instanceof HttpResponse) { + return createHttpMessageWrapper((HttpRequest) req, (HttpResponse) resp, context); + } else { + return new MessageWrapper(req, resp, context); + } + } + + @Override + public MessageWrapper createWrapper(Object obj) { + if (obj instanceof HttpMessage) { + HttpMessage message = (HttpMessage) obj; + if (message.isRequest()) { + return createHttpMessageWrapper((HttpRequest) message, null, null); + } else { + return createHttpMessageWrapper(null, (HttpResponse) message, null); + } + } else { + return new MessageWrapper(obj, null, null); + } + } + + public HttpMessageWrapper createHttpMessageWrapper(HttpRequest req, HttpResponse resp, FlowContext context) { + HttpFilterRequestWrapper reqWrapper = (HttpFilterRequestWrapper) createHttpMessageWrapper(req); + HttpFilterResponseWrapper respWrapper = (HttpFilterResponseWrapper) createHttpMessageWrapper(resp); + + HttpFlowContext httpContext; + HttpFilterResponseWrapper origResp; + if (context != null) { + httpContext = context.getParamValue(HttpFlowConst.PARAM_HTTP_CONTEXT); + origResp = (HttpFilterResponseWrapper) createHttpMessageWrapper(httpContext.origResponse()); + } else { + httpContext = null; + origResp = null; + } + + return new HttpMessageWrapper(reqWrapper, respWrapper, context, origResp, httpContext); + } + + public HttpFilterMessageWrapper createHttpMessageWrapper(HttpMessage message) { + if (message == null) { + return null; + } + + if (message.isRequest()) { + return new HttpFilterRequestWrapper((HttpRequest) message); + } else { + return new HttpFilterResponseWrapper((HttpResponse) message); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/FilterDirection.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,11 @@ +package com.passus.st.filter; + +/** + * + * @author Mirosław Hawrot + */ +public enum FilterDirection { + + IN, OUT, BOTH + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/FlowFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,34 @@ +package com.passus.st.filter; + +import com.passus.config.Configurable; +import com.passus.config.Configuration; +import com.passus.config.ConfigurationContext; +import com.passus.st.client.FlowContext; + +public interface FlowFilter extends Configurable { + + int DENY = -1; + + int DUNNO = 0; + + int ACCEPT = 1; + + default void reset() { + + } + + @Override + default void configure(Configuration config, ConfigurationContext context) { + + } + + default int filterInbound(Object req, Object resp, FlowContext context) { + return DUNNO; + } + + default int filterOutbound(Object req, Object resp, FlowContext context) { + return DUNNO; + } + + FlowFilter instanceForWorker(int index); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/FlowFilterChain.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,96 @@ +package com.passus.st.filter; + +import com.passus.filter.Filter; +import com.passus.st.client.FlowContext; + +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +public class FlowFilterChain { + + protected final LinkedList<FlowFilter> filters = new LinkedList<>(); + + public List<FlowFilter> getFilters() { + return Collections.unmodifiableList(filters); + } + + @SuppressWarnings("unchecked") + public void addFilter(FlowFilter filter) { + filters.add(filter); + } + + public void clear() { + filters.clear(); + } + + public boolean isEmpty() { + return filters.isEmpty(); + } + + @SuppressWarnings("unchecked") + public int filterOutbound(Object request, Object resp, FlowContext context) { + Iterator<FlowFilter> it = filters.iterator(); + while (it.hasNext()) { + FlowFilter f = it.next(); + int res = f.filterOutbound(request, resp, context); + if (res != Filter.DUNNO) { + return res; + } + } + + return Filter.ACCEPT; + } + + @SuppressWarnings("unchecked") + public int filterInbound(Object request, Object resp, FlowContext context) { + Iterator<FlowFilter> it = filters.iterator(); + while (it.hasNext()) { + FlowFilter f = it.next(); + int res = f.filterInbound(request, resp, context); + if (res != Filter.DUNNO) { + return res; + } + } + + return Filter.ACCEPT; + } + + public void reset() { + Iterator<FlowFilter> it = filters.iterator(); + while (it.hasNext()) { + FlowFilter f = it.next(); + f.reset(); + } + } + + public FlowFilterChain instanceForWorker(int index) { + FlowFilterChain copy = new FlowFilterChain(); + + Iterator<FlowFilter> it = filters.iterator(); + while (it.hasNext()) { + FlowFilter f = it.next(); + copy.addFilter(f.instanceForWorker(index)); + } + + return copy; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("FlowFilterChain@").append(System.identityHashCode(this)); + sb.append(" {"); + + Iterator<FlowFilter> it = filters.iterator(); + while (it.hasNext()) { + FlowFilter f = it.next(); + sb.append(f).append(", "); + } + sb.append("}"); + + return sb.toString(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/FlowFilterFactory.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,18 @@ +package com.passus.st.filter; + +import com.passus.net.http.HttpRequest; +import com.passus.net.http.HttpResponse; +import com.passus.st.client.FlowContext; +import com.passus.st.client.http.filter.HttpMessageWrapper; + +public interface FlowFilterFactory { + + FlowFilterFactory DEFAULT_FACTORY = new DefaultFlowFilterFactory(); + + MessageWrapper createWrapper(Object req, Object resp, FlowContext context); + + MessageWrapper createWrapper(Object obj); + + HttpMessageWrapper createHttpMessageWrapper(HttpRequest req, HttpResponse resp, FlowContext context); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/FlowFilterNodeDefinitionCreator.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,22 @@ +package com.passus.st.filter; + +import com.passus.config.schema.DynaKeyValueVaryListNodeDefinition; +import com.passus.config.schema.NodeDefinition; +import com.passus.config.schema.NodeDefinitionCreator; + +/** + * @author Mirosław Hawrot + */ +public class FlowFilterNodeDefinitionCreator implements NodeDefinitionCreator { + + public static NodeDefinition createFiltersList(boolean transformToObject) { + return new DynaKeyValueVaryListNodeDefinition("type", FlowFilterPluginFactory.getInstance()) + .setTransformToPluginObject(transformToObject); + } + + @Override + public NodeDefinition create() { + return createFiltersList(true); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/FlowFilterPluginFactory.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,24 @@ +package com.passus.st.filter; + +import com.passus.commons.plugin.PluginFactory; +import com.passus.st.plugin.PluginConstants; + +/** + * @author Mirosław Hawrot + */ +public final class FlowFilterPluginFactory extends PluginFactory<FlowFilter> { + + private static FlowFilterPluginFactory instance; + + public FlowFilterPluginFactory() { + super(PluginConstants.CATEGORY_FLOW_FILTER, FlowFilter.class); + } + + public static synchronized FlowFilterPluginFactory getInstance() { + if (instance == null) { + instance = new FlowFilterPluginFactory(); + } + + return instance; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/FlowFiltersConfigurator.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,67 @@ +package com.passus.st.filter; + +import com.passus.commons.annotations.Plugin; +import com.passus.config.*; +import com.passus.config.schema.NodeDefinition; +import com.passus.config.validation.Errors; +import com.passus.st.plugin.PluginConstants; +import com.passus.st.utils.ConfigurationContextConsts; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +/** + * @author Mirosław Hawrot + */ +@Plugin(name = FlowFiltersConfigurator.DOMAIN, category = PluginConstants.CATEGORY_DOMAIN_CONFIGURATOR) +public class FlowFiltersConfigurator implements DomainConfigurator { + + public static final String DOMAIN = "filters"; + + private static final FlowFilterNodeDefinitionCreator CREATOR = new FlowFilterNodeDefinitionCreator(); + + private final NodeDefinition nodeDef = CREATOR.create(); + + @Override + public String getDomain() { + return DOMAIN; + } + + public static List<FlowFilter> getFilters(File configFile, Errors errors, ConfigurationContext context) throws IOException, NodeException { + Configuration config = YamlConfigurationReader.readFromFile(configFile); + return getFilters(config, errors, context); + } + + public static List<FlowFilter> getFilters(String configStr, Errors errors, ConfigurationContext context) throws IOException, NodeException { + Configuration config = YamlConfigurationReader.readFromString(configStr); + return getFilters(config, errors, context); + } + + public static List<FlowFilter> getFilters(Configuration config, Errors errors, ConfigurationContext context) { + NodeDefinition nodeDef = CREATOR.create(); + return ConfigurationUtils.getDomainObjects(config, errors, context, DOMAIN, nodeDef); + } + + @Override + public void validate(Configuration config, Errors errors, ConfigurationContext context) { + CCompositeNode rootNode = config.getRootNode(); + nodeDef.validate(rootNode, errors, context); + } + + @Override + public void configure(Configuration config, Errors errors, ConfigurationContext context) { + CCompositeNode rootNode = config.getRootNode(); + nodeDef.transform(rootNode, errors, context); + if (!errors.hasError()) { + try { + List<FlowFilter> filters = ConfigurationUtils.convertToList(rootNode, FlowFilter.class); + context.add(ConfigurationContextConsts.FLOW_FILTERS, filters); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/MatchFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,94 @@ +package com.passus.st.filter; + +import com.passus.commons.Assert; +import com.passus.commons.annotations.Plugin; +import com.passus.config.Configuration; +import com.passus.config.ConfigurationContext; +import com.passus.config.annotations.NodeDefinitionCreate; +import com.passus.config.schema.NodeDefinition; +import com.passus.config.schema.NodeDefinitionCreator; +import com.passus.st.client.FlowContext; +import com.passus.st.plugin.PluginConstants; + +import static com.passus.config.schema.ConfigurationSchemaBuilder.*; + +/** + * @author Mirosław Hawrot + */ +@NodeDefinitionCreate(MatchFilter.MatchFilterNodeDefCreator.class) +@Plugin(name = MatchFilter.TYPE, category = PluginConstants.CATEGORY_FLOW_FILTER) +public class MatchFilter implements FlowFilter { + + public static final String TYPE = "matcher"; + + private MessagePredicate predicate; + + private boolean acceptOnMatch = true; + + private final FlowFilterFactory filterFactory; + + public MatchFilter() { + this(FlowFilterFactory.DEFAULT_FACTORY); + } + + public MatchFilter(FlowFilterFactory filterFactory) { + Assert.notNull(filterFactory, "filterFactory"); + this.filterFactory = filterFactory; + } + + public MessagePredicate getPredicate() { + return predicate; + } + + public void setPredicate(MessagePredicate predicate) { + this.predicate = predicate; + } + + public boolean isAcceptOnMatch() { + return acceptOnMatch; + } + + public void setAcceptOnMatch(boolean acceptOnMatch) { + this.acceptOnMatch = acceptOnMatch; + } + + @Override + public void configure(Configuration config, ConfigurationContext context) { + predicate = (MessagePredicate) config.get("matches"); + acceptOnMatch = config.getBoolean("acceptOnMatch", true); + } + + @Override + public int filterOutbound(Object request, Object resp, FlowContext context) { + if (predicate == null) { + return DUNNO; + } + + boolean match = predicate.test(filterFactory.createWrapper(request, resp, context)); + if (!match) { + return DUNNO; + } + + return acceptOnMatch ? ACCEPT : DENY; + } + + @Override + public MatchFilter instanceForWorker(int index) { + MatchFilter filter = new MatchFilter(); + filter.acceptOnMatch = acceptOnMatch; + filter.predicate = predicate; + return filter; + } + + public static class MatchFilterNodeDefCreator implements NodeDefinitionCreator { + + @Override + public NodeDefinition create() { + return mapDef( + tupleDef("acceptOnMatch", valueDefBool()).setRequired(false), + tupleDef("matches", new MessagePredicateNodeDefinition()) + ); + } + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/MessagePredicate.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,56 @@ +package com.passus.st.filter; + +import com.passus.commons.Assert; +import com.passus.commons.ConversionException; +import com.passus.config.NodeException; +import com.passus.st.client.FlowContext; + +import java.io.IOException; +import java.util.function.Predicate; + +import static com.passus.st.filter.FlowFilterFactory.DEFAULT_FACTORY; + +public class MessagePredicate<T> implements Predicate<T> { + + protected final Predicate predicate; + + protected final FlowFilterFactory filterFactory; + + public MessagePredicate(Predicate predicate) { + this(predicate, DEFAULT_FACTORY); + } + + public MessagePredicate(Predicate predicate, FlowFilterFactory filterFactory) { + Assert.notNull(predicate, "predicate"); + Assert.notNull(filterFactory, "filterFactory"); + this.predicate = predicate; + this.filterFactory = filterFactory; + } + + public Predicate getPredicate() { + return predicate; + } + + public boolean test(Object req, Object resp, FlowContext context) { + return test(filterFactory.createWrapper(req, resp, context)); + } + + public boolean test(MessageWrapper wrapper) { + return predicate.test(wrapper); + } + + @Override + public boolean test(T message) { + return predicate.test(filterFactory.createWrapper(message)); + } + + @Override + public String toString() { + return predicate.toString(); + } + + public static MessagePredicate parse(String content) throws ConversionException, IOException, NodeException { + Predicate predicate = Transformers.PREDICATE.transform(content); + return new MessagePredicate(predicate); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/MessagePredicateNodeDefinition.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,79 @@ +package com.passus.st.filter; + +import com.passus.commons.ConversionException; +import com.passus.commons.utils.ArrayUtils; +import com.passus.config.*; +import com.passus.config.schema.NodeDefinition; +import com.passus.config.validation.Errors; +import com.passus.filter.config.PredicateNodeTransformer; +import com.passus.lookup.filter.LookupKeyExistsLeftOperatorTransformer; +import com.passus.lookup.filter.LookupValueExtractorTransformer; + +import java.util.Set; +import java.util.function.Predicate; + +import static com.passus.config.validation.ValidationDefaultMessages.GENERAL_CONVERSION_ERROR; + +/** + * @author Mirosław Hawrot + */ +public class MessagePredicateNodeDefinition extends NodeDefinition<MessagePredicateNodeDefinition> { + + private static final PredicateNodeTransformer TRANSFORMER = Transformers.PREDICATE; + + private final static Set<Class<? extends CNode>> SUPPORTED = ArrayUtils.asUnmodifiableSet(CListNode.class, CMapNode.class); + + @Override + public Set<Class<? extends CNode>> getSupportedNode() { + return SUPPORTED; + } + + @Override + protected void doValidate(CNode node, Errors errors, ConfigurationContext context) { + try { + // TODO: refactor + LookupKeyExistsLeftOperatorTransformer lookupKeyExistsTransformer = Transformers.lookupKeyExistsTransformer(context); + LookupValueExtractorTransformer lookupValueTransformer = Transformers.lookupValueTransformer(context); + TRANSFORMER.addLeftOperatorTransformer(lookupKeyExistsTransformer); + TRANSFORMER.addValueExtractorTransformer(lookupValueTransformer); + TRANSFORMER.transform(node); + TRANSFORMER.removeLeftOperatorTransformer(lookupKeyExistsTransformer); + TRANSFORMER.removeValueExtractorTransformer(lookupValueTransformer); + } catch (NodeConversionException ex) { + errors.reject(node, ex.getMessage()); + } catch (ConversionException ex) { + errors.reject(node, GENERAL_CONVERSION_ERROR); + } + } + + @Override + protected CNode doTransform(CNode node, Errors errors, ConfigurationContext context, boolean reverse) { + if (reverse) { + throw new UnsupportedOperationException("Not supported yet."); + } else { + try { + // TODO: refactor + LookupKeyExistsLeftOperatorTransformer lookupKeyExistsTransformer = Transformers.lookupKeyExistsTransformer(context); + LookupValueExtractorTransformer lookupValueTransformer = Transformers.lookupValueTransformer(context); + TRANSFORMER.addLeftOperatorTransformer(lookupKeyExistsTransformer); + TRANSFORMER.addValueExtractorTransformer(lookupValueTransformer); + Predicate predicate = TRANSFORMER.transform(node); + TRANSFORMER.removeLeftOperatorTransformer(lookupKeyExistsTransformer); + TRANSFORMER.removeValueExtractorTransformer(lookupValueTransformer); + return new CValueNode(new MessagePredicate(predicate)); + } catch (NodeConversionException ex) { + errors.reject(node, ex.getMessage()); + } catch (ConversionException ex) { + errors.reject(node, GENERAL_CONVERSION_ERROR); + } + } + + return null; + } + + @Override + protected boolean doEquals(CNode node1, CNode node2) { + throw new UnsupportedOperationException("Not supported yet."); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/MessageWrapper.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,27 @@ +package com.passus.st.filter; + +import com.passus.st.client.FlowContext; + +public class MessageWrapper<R, S> { + + protected final R req; + + protected final S resp; + + protected final FlowContext context; + + public MessageWrapper(R req, S resp, FlowContext context) { + this.req = req; + this.resp = resp; + this.context = context; + } + + public R getReq() { + return req; + } + + public S getResp() { + return resp; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/MvelFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,162 @@ +package com.passus.st.filter; + +import com.passus.commons.Assert; +import com.passus.commons.annotations.Plugin; +import com.passus.config.Configuration; +import com.passus.config.ConfigurationContext; +import com.passus.config.annotations.NodeDefinitionCreate; +import com.passus.config.schema.NodeDefinition; +import com.passus.config.schema.NodeDefinitionCreator; +import com.passus.net.http.HttpRequest; +import com.passus.st.client.FlowContext; +import com.passus.st.client.http.HttpScopes; +import com.passus.st.config.StringSourceNodeDefinition; +import com.passus.st.config.StringToExecutableStatementValueTransformer; +import com.passus.st.plugin.PluginConstants; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.mvel2.compiler.ExecutableStatement; +import org.mvel2.integration.VariableResolverFactory; +import org.mvel2.integration.impl.CachingMapVariableResolverFactory; + +import java.util.HashMap; +import java.util.Map; + +import static com.passus.config.schema.ConfigurationSchemaBuilder.*; +import static com.passus.st.client.http.filter.HttpFlowUtils.extractHttpContext; + +/** + * @author Mirosław Hawrot + */ +@NodeDefinitionCreate(MvelFilter.MvelFilterNodeDefCreator.class) +@Plugin(name = MvelFilter.TYPE, category = PluginConstants.CATEGORY_FLOW_FILTER) +public class MvelFilter implements FlowFilter { + + public static final String TYPE = "mvel"; + + private static final Logger LOGGER = LogManager.getLogger(MvelFilter.class); + + private VariableResolverFactory globalFactory; + + private ExecutableStatement statement; + + private FilterDirection direction = FilterDirection.OUT; + + public MvelFilter() { + } + + public MvelFilter(ExecutableStatement statement, FilterDirection direction) { + Assert.notNull(statement, "statement"); + Assert.notNull(direction, "direction"); + this.statement = statement; + this.direction = direction; + } + + public VariableResolverFactory getGlobalFactory() { + return globalFactory; + } + + public void setGlobalFactory(VariableResolverFactory globalFactory) { + this.globalFactory = globalFactory; + } + + public FilterDirection getDirection() { + return direction; + } + + public void setDirection(FilterDirection direction) { + Assert.notNull(direction, "direction"); + this.direction = direction; + } + + public ExecutableStatement getStatement() { + return statement; + } + + public void setStatement(ExecutableStatement statement) { + this.statement = statement; + } + + @Override + public void configure(Configuration config, ConfigurationContext context) { + direction = config.get("dir", FilterDirection.OUT); + statement = (ExecutableStatement) config.get("script"); + } + + private int filter(Object req, Object resp, FlowContext context) { + if (statement == null) { + return DUNNO; + } + + Map<String, Object> vars = new HashMap<>(3); + vars.put("$req", req); + vars.put("$resp", resp); + vars.put("$context", context); + if (context != null && req instanceof HttpRequest) { + HttpRequest httpReq = (HttpRequest) req; + HttpScopes scopes = extractHttpContext(context).scopes(); + vars.put("$extractHttpContext", scopes); + vars.put("$httpSession", scopes.getSession(httpReq)); + } + + CachingMapVariableResolverFactory factory = new CachingMapVariableResolverFactory(vars); + if (globalFactory != null) { + factory.setNextFactory(globalFactory); + } + + try { + Object out = statement.getValue(null, factory); + if (out instanceof Integer) { + int value = (Integer) out; + if (value < 0) { + return DENY; + } else if (value > 0) { + return ACCEPT; + } + + return DUNNO; + } + } catch (Throwable th) { + LOGGER.trace(th); + } + + return DUNNO; + } + + @Override + public int filterOutbound(Object req, Object resp, FlowContext context) { + if (direction == FilterDirection.BOTH || direction == FilterDirection.OUT) { + return filter(req, resp, context); + } + + return DUNNO; + } + + @Override + public int filterInbound(Object req, Object resp, FlowContext context) { + if (direction == FilterDirection.BOTH || direction == FilterDirection.IN) { + return filter(req, resp, context); + } + + return DUNNO; + } + + @Override + public FlowFilter instanceForWorker(int index) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public static final class MvelFilterNodeDefCreator implements NodeDefinitionCreator { + + @Override + public NodeDefinition create() { + return mapDef( + tupleDef("dir", enumDef(FilterDirection.class)).setRequired(false), + tupleDef("script", new StringSourceNodeDefinition() + .setTransformer(new StringToExecutableStatementValueTransformer()) + ) + ); + } + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/SequenceFilter.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,481 @@ +package com.passus.st.filter; + +import com.passus.commons.Assert; +import com.passus.commons.annotations.Plugin; +import com.passus.commons.metric.MapMetric; +import com.passus.commons.service.Registry; +import com.passus.commons.time.SystemTimeGenerator; +import com.passus.commons.time.TimeAware; +import com.passus.commons.time.TimeGenerator; +import com.passus.config.*; +import com.passus.config.annotations.NodeDefinitionCreate; +import com.passus.config.schema.*; +import com.passus.config.validation.Errors; +import com.passus.filter.ValueExtractor; +import com.passus.filter.ValueExtractorParser; +import com.passus.filter.config.PredicateNodeTransformer; +import com.passus.st.client.FlowContext; +import com.passus.st.client.http.ReporterDestination; +import com.passus.st.plugin.PluginConstants; + +import java.io.Serializable; +import java.text.ParseException; +import java.util.*; +import java.util.function.Predicate; + +import static com.passus.config.schema.ConfigurationSchemaBuilder.*; + +/** + * @author mikolaj.podbielski + */ +@NodeDefinitionCreate(SequenceFilter.NodeDefCreator.class) +@Plugin(name = SequenceFilter.TYPE, category = PluginConstants.CATEGORY_FLOW_FILTER) +public class SequenceFilter implements FlowFilter, TimeAware { + + public static class SequenceItem { + + private final Predicate predicate; + private boolean mustOccur = true; + private long time = 10_000; + private int num; + private String alias; + private String[] aliases; + + public SequenceItem(Predicate predicate, int num) { + this(predicate); + this.num = num; + } + + public SequenceItem(Predicate predicate) { + if (predicate == null) { + throw new NullPointerException(); + } + this.predicate = predicate; + } + + public Predicate getPredicate() { + return predicate; + } + + public int getNum() { + return num; + } + + public void setNum(int num) { + this.num = num; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + if (time <= 0) { + throw new IllegalArgumentException("Time must be greater than zero."); + } + this.time = time; + } + + public String getAlias() { + return alias; + } + + public void setAlias(String alias) { + this.alias = alias; + aliases = null; + } + + public boolean isMustOccur() { + return mustOccur; + } + + public void setMustOccur(boolean mustOccur) { + this.mustOccur = mustOccur; + } + + private boolean match(Map<String, Object> value) { + return predicate.test(value); + } + + private String[] getAliases() { + if (aliases == null) { + if (alias != null) { + aliases = new String[2]; + aliases[1] = alias; + } else { + aliases = new String[1]; + } + + aliases[0] = "_i" + num; + } + + return aliases; + } + } + + private static class SeqChainItem { + + private final SequenceItem seq; + private SeqChainItem next; + private final long startTime; + private final long endTime; + private boolean active = true; + + public SeqChainItem(SequenceItem seq, long startTime) { + this.seq = seq; + this.startTime = startTime; + this.endTime = startTime + seq.time; + } + + public void setNext(SeqChainItem next) { + this.next = next; + } + + public long getStartTime() { + return startTime; + } + + public long getEndTime() { + return endTime; + } + + public boolean match(Map<String, Object> value) { + return seq.match(value); + } + + public SeqChainItem getNext() { + return next; + } + + public boolean inTimeRange(long time) { + return (startTime <= time && time < endTime); + } + } + + private static class SeqChain { + + private SeqChainItem seqItem; + + private final Map<String, Object> valueMap; +// private Filterable value = new FilterableMap(); +// private FlowMarker flowMarker; + + public SeqChain(SequenceItem[] seqItems, long startTime, Map<String, Object> valueMap) { + this.valueMap = valueMap; + + SeqChainItem curItem = new SeqChainItem(seqItems[1], startTime); + seqItem = curItem; + + for (int i = 2; i < seqItems.length; i++) { + SeqChainItem nexItem = new SeqChainItem(seqItems[i], curItem.getStartTime()); + curItem.setNext(nexItem); + curItem = nexItem; + } + } + + public void updateValue(MessageWrapper wrapper) { + valueMap.put("req", wrapper.getReq()); + valueMap.put("resp", wrapper.getResp()); + } + + public void persistsValue(MessageWrapper wrapper, String[] aliases) { + for (String alias : aliases) { + valueMap.put(alias, wrapper); + } + } + + public boolean hasNext() { + return (seqItem != null && seqItem.getNext() != null); + } + + public boolean next() { + if (seqItem == null) { + return false; + } + + seqItem = seqItem.getNext(); + return true; + } + + public boolean rewind(long time) { + if (seqItem == null) { + return false; + } + + while (hasNext()) { + if (seqItem.inTimeRange(time)) { + return true; + } else if (seqItem.seq.mustOccur) { + return false; + } + + next(); + } + + return false; + } + } + + public static final String TYPE = "sequence"; + + private final List<SeqChain> chains = new ArrayList<>(); + private SequenceListener listener = (e) -> { + }; + private SequenceItem[] seqItems; + private Map<String, ValueExtractor> values = Collections.EMPTY_MAP; + + private final FlowFilterFactory filterFactory; + + private TimeGenerator timeGenerator = new SystemTimeGenerator(); + + public SequenceFilter() { + this(FlowFilterFactory.DEFAULT_FACTORY); + } + + public SequenceFilter(FlowFilterFactory filterFactory) { + Assert.notNull(filterFactory, "filterFactory"); + this.filterFactory = filterFactory; + } + + public SequenceListener getListener() { + return listener; + } + + public void setListener(SequenceListener listener) { + this.listener = listener; + } + + public SequenceItem[] getSeqItems() { + return seqItems; + } + + public void setSeqItems(SequenceItem[] seqItems) { + this.seqItems = seqItems; + } + + public Map<String, ValueExtractor> getValues() { + return values; + } + + public void setValues(Map<String, ValueExtractor> values) { + this.values = values; + } + + @Override + public TimeGenerator getTimeGenerator() { + return timeGenerator; + } + + @Override + public void setTimeGenerator(TimeGenerator timeGenerator) { + Assert.notNull(timeGenerator, "timeGenerator"); + this.timeGenerator = timeGenerator; + } + + private void processValue(long now, MessageWrapper value) { + Iterator<SeqChain> iterator = chains.iterator(); + while (iterator.hasNext()) { + SeqChain chain = iterator.next(); + + if (chain.seqItem.startTime <= now) { + if (!chain.seqItem.inTimeRange(now) && !chain.rewind(now)) { + chain.persistsValue(value, chain.seqItem.seq.getAliases()); + fireEvent(chain); + iterator.remove(); + } else if (chain.seqItem.active) { + chain.updateValue(value); + + if (chain.seqItem.match(chain.valueMap)) { + if (!chain.seqItem.seq.mustOccur) { + iterator.remove(); + } else { + chain.persistsValue(value, chain.seqItem.seq.getAliases()); + if (!chain.hasNext()) { + fireEvent(chain); + iterator.remove(); + } else if (!chain.next()) { + fireEvent(chain); + iterator.remove(); + } + } + } + } + } + } + + final Map<String, Object> valueMap = new HashMap<>(); + valueMap.put("req", value.getReq()); + valueMap.put("resp", value.getResp()); + + if (seqItems[0].match(valueMap)) { + SeqChain chain = new SeqChain(seqItems, now, valueMap); + chain.persistsValue(value, seqItems[0].getAliases()); + chains.add(chain); + } + } + + private void fireEvent(SeqChain chain) { + Map<String, Serializable> result; + + if (values.isEmpty()) { + result = Collections.emptyMap(); + } else { + result = new HashMap<>(); + Map<String, Object> persisted = chain.valueMap; + for (Map.Entry<String, ValueExtractor> e : values.entrySet()) { + Object value = e.getValue().extract(persisted); + if (value instanceof Serializable) { + result.put(e.getKey(), (Serializable) value); + } + } + } + + listener.sequenceDetected(new MapMetric("sequence", result)); + } + + @Override + public int filterInbound(Object req, Object resp, FlowContext context) { + MessageWrapper wrapper = filterFactory.createWrapper(req, resp, context); + processValue(timeGenerator.currentTimeMillis(), wrapper); + return DUNNO; + } + + @Override + public void reset() { + chains.clear(); + } + + @Override + public SequenceFilter instanceForWorker(int index) { + SequenceFilter filter = new SequenceFilter(); + filter.listener = listener; + filter.seqItems = seqItems; + filter.values = values; + return filter; + } + + @Override + public void configure(Configuration config, ConfigurationContext context) { + List<SequenceItem> itemsList = (List<SequenceItem>) config.get("sequence"); + seqItems = itemsList.toArray(new SequenceItem[itemsList.size()]); + for (int i = 0; i < seqItems.length; ++i) { + seqItems[i].setNum(i); + } + + values = (Map<String, ValueExtractor>) config.get("values", Collections.EMPTY_MAP); + ReporterDestination reporterDestination = Registry.getInstance().get( + ReporterDestination.SERVICE_NAME, ReporterDestination.class); + if (reporterDestination != null) { + listener = reporterDestination; + } + } + + public static class NodeDefCreator implements NodeDefinitionCreator { + + @Override + public NodeDefinition create() { + MapNodeDefinition elementDef = mapDef( + tupleDef("match", new MessagePredicateNodeDefinition()), + tupleDef("mustOccur", valueDef(Boolean.class)).setRequired(false), + tupleDef("time", valueDef(Long.class)).setRequired(false), + tupleDef("alias", valueDef()).setRequired(false) + ); + elementDef.setTransformer(new SequencesNodeTransformer()); + // TODO: mustOccur and time required in all steps but first + + return mapDef( + tupleDef("sequence", new ListNodeDefinition(elementDef).setMinNumberOfValues(2)), + tupleDef("values", new MappingNodeDefinition().setTransformer(new ValuesNodeTransformer())).setRequired(false) + ); + } + + } + + private static class SequencesNodeTransformer implements NodeTransformer<CNode> { + + private static final PredicateNodeTransformer TRANSFORMER = Transformers.PREDICATE; + + @Override + public CNode transform(CNode node, Errors errors, ConfigurationContext context) { + try { + CMapNode mapNode = (CMapNode) node; + List<CTupleNode> tupleNodes = mapNode.getChildren(); + + Predicate predicate = null; + boolean mustOccur = true; + long time = 0; + String alias = null; + for (CTupleNode tupleNode : tupleNodes) { + String name = tupleNode.getName(); + CNode valueNode = tupleNode.getNode(); + switch (name) { + case "match": + predicate = TRANSFORMER.transform(valueNode); + break; + case "mustOccur": + mustOccur = (Boolean) getValue(valueNode); + break; + case "time": + time = (Long) getValue(valueNode); + break; + case "alias": + alias = (String) getValue(valueNode); + break; + } + } + SequenceItem item = new SequenceItem(predicate); + if (time > 0) { + item.setTime(time); + } + item.setMustOccur(mustOccur); + item.setAlias(alias); + return new CValueNode(item); + } catch (Exception ex) { + return node; + } + } + + @Override + public CNode reverseTransform(CNode node, Errors errors, ConfigurationContext context) { + throw new UnsupportedOperationException("Not supported yet."); + } + + } + + private static class ValuesNodeTransformer implements NodeTransformer<CNode> { + + @Override + public CNode transform(CNode node, Errors errors, ConfigurationContext context) { + Map<String, ValueExtractor> result = new HashMap<>(); + + CMapNode mapNode = (CMapNode) node; + List<CTupleNode> tupleNodes = mapNode.getChildren(); + for (CTupleNode tupleNode : tupleNodes) { + String name = tupleNode.getName(); + CValueNode valueNode = (CValueNode) tupleNode.getNode(); + String value = (String) valueNode.getValue(); + try { + errors.pushNestedPath(name); + ValueExtractor extractor = ValueExtractorParser.DEFAULT.parse(value); + result.put(name, extractor); + } catch (ParseException ex) { + errors.reject(tupleNode, "Invalid expression: \"%s\"", value); + } finally { + errors.popNestedPath(); + } + } + return new CValueNode(result); + } + + @Override + public CNode reverseTransform(CNode node, Errors errors, ConfigurationContext context) { + throw new UnsupportedOperationException("Impossible."); // ValueExtractor + } + + } + + private static Object getValue(CNode node) { + CValueNode valueNode = (CValueNode) node; + return valueNode.getValue(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/filter/SequenceListener.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,12 @@ +package com.passus.st.filter; + +import com.passus.commons.metric.MapMetric; + +/** + * + * @author mikolaj.podbielski + */ +public interface SequenceListener { + + void sequenceDetected(MapMetric sequence); +}
--- a/stress-tester/src/main/java/com/passus/st/job/TestJob.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/main/java/com/passus/st/job/TestJob.java Thu Mar 26 13:27:52 2020 +0100 @@ -4,7 +4,7 @@ import com.passus.config.ConfigurationContext; import com.passus.filter.ValueExtractor; import com.passus.st.client.*; -import com.passus.st.client.filter.FlowFilter; +import com.passus.st.filter.FlowFilter; import com.passus.st.client.http.ReporterDestination; import com.passus.st.client.http.filter.HttpVarsFilter; import com.passus.st.emitter.Emitter;
--- a/stress-tester/src/test/java/com/passus/st/ConverterHttpClientTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/ConverterHttpClientTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -4,13 +4,13 @@ import com.passus.st.client.SessionPayloadEvent; import com.passus.st.client.credentials.Credentials; import com.passus.st.client.credentials.CredentialsProvider; -import com.passus.st.client.filter.*; import com.passus.st.client.http.filter.*; import com.passus.st.client.http.filter.HttpMessageModificationOperations.PostDataSetParamOperation; import com.passus.st.client.http.filter.HttpMessageModificationOperations.SetCookieOperation; import com.passus.st.client.http.filter.HttpMessageModificationOperations.SetHeaderOperation; import com.passus.st.client.http.filter.HttpMessageModificationOperations.SetQueryParameterOperation; import com.passus.st.emitter.SessionInfo; +import com.passus.st.filter.*; import com.passus.st.source.ArrayListEventDestination; import com.passus.st.source.NullEventDestination; import com.passus.st.utils.TestHttpUtils;
--- a/stress-tester/src/test/java/com/passus/st/FilterScanner.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/FilterScanner.java Thu Mar 26 13:27:52 2020 +0100 @@ -1,6 +1,6 @@ package com.passus.st; -import com.passus.st.client.filter.FlowFilterPluginFactory; +import com.passus.st.filter.FlowFilterPluginFactory; /** *
--- a/stress-tester/src/test/java/com/passus/st/client/FlowFilterChainTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/FlowFilterChainTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -1,7 +1,7 @@ package com.passus.st.client; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFilterChain; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFilterChain; import org.testng.annotations.Test; import static com.passus.st.client.http.filter.HttpFilter.*;
--- a/stress-tester/src/test/java/com/passus/st/client/dns/filter/DnsRecordTypeFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/dns/filter/DnsRecordTypeFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -3,8 +3,8 @@ import com.passus.config.NodeException; import com.passus.config.validation.Errors; import com.passus.net.dns.DnsRecordType; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFiltersConfigurator; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFiltersConfigurator; import org.testng.annotations.Test; import java.io.IOException;
--- a/stress-tester/src/test/java/com/passus/st/client/filter/CounterFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.config.validation.Errors; -import com.passus.filter.AndPredicate; -import com.passus.filter.ComparisonOperator; -import com.passus.filter.ComparisonPredicate; -import com.passus.net.http.*; -import org.testng.annotations.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.testng.AssertJUnit.assertEquals; -import static org.testng.AssertJUnit.assertTrue; - -public class CounterFilterTest { - - @Test - public void testFilterInbound() { - HttpRequest req = HttpRequestBuilder.get("http://example.com").build(); - HttpResponse resp = HttpResponseBuilder.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); - - TestListener listener = new TestListener(); - - MessagePredicate predicate = FilterTestUtils.createPredicate("{'@resp.status.code': 500}"); - CounterFilter filter = new CounterFilter(); - filter.setLimit(2); - filter.setName("filter status code 500"); - filter.setPredicate(predicate); - filter.setListener(listener); - - filter.filterInbound(req, resp, null); - assertEquals(0, listener.events.size()); - filter.filterInbound(req, resp, null); - assertEquals(1, listener.events.size()); - } - - @Test - public void testConfigure() throws Exception { - String filterConfig = "filters:\n" - + " - type: counter\n" - + " name: 'filter x'\n" - + " limit: 3\n" - + " applyIf: {'@resp.status.code': 404}\n"; - - Errors errors = new Errors(); - List<FlowFilter> filters = FlowFiltersConfigurator.getFilters(filterConfig, errors, null); - FilterTestUtils.printErrors(errors); - - assertEquals(0, errors.getErrorCount()); - assertEquals(1, filters.size()); - assertTrue(filters.get(0) instanceof CounterFilter); - - CounterFilter filter = (CounterFilter) filters.get(0); - assertEquals(3, filter.getLimit()); - assertEquals("filter x", filter.getName()); - - AndPredicate<? extends Object> andPredicate = (AndPredicate) filter.getPredicate().getPredicate(); - assertEquals(1, andPredicate.getSubPredicates().size()); - ComparisonPredicate predicate = (ComparisonPredicate) andPredicate.getSubPredicates().get(0); - assertEquals("resp.status.code", predicate.getFieldName()); - assertEquals(ComparisonOperator.EQUAL, predicate.getOperator()); - } - - private static class TestListener implements CounterListener { - - private final ArrayList<Event> events = new ArrayList<>(); - - @Override - public void limitReached(Event event) { - events.add(event); - } - - } - -} \ No newline at end of file
--- a/stress-tester/src/test/java/com/passus/st/client/filter/FilterTestUtils.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.commons.utils.ReflectionUtils; -import com.passus.config.validation.Errors; -import com.passus.config.validation.ObjectError; -import com.passus.filter.config.PredicateNodeTransformer; -import com.passus.net.http.HttpMessage; -import com.passus.st.ParametersBag; -import static com.passus.st.client.http.HttpConsts.TAG_SESSION_ID; -import static com.passus.st.client.http.HttpConsts.ZONE_DEFAULT; - -import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.MessagePredicate; -import com.passus.st.client.http.HttpFlowConst; -import com.passus.st.client.http.HttpFlowContext; -import com.passus.st.client.http.HttpScopes; -import com.passus.st.filter.Transformers; -import java.util.List; -import java.util.Map; -import java.util.function.Predicate; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * - * @author mikolaj.podbielski - */ -public class FilterTestUtils { - - private static final boolean DEFAULT_USE_ACCELERATED_EXTRACTORS = true; - - public static FlowContext createMockContext() { - return createMockContext(new HttpScopes()); - } - - public static FlowContext createMockContext(HttpScopes scopes) { - FlowContext mockContext = mock(FlowContext.class); - HttpFlowContext mockHttpContext = mock(HttpFlowContext.class); - when(mockContext.getParamValue(HttpFlowConst.PARAM_HTTP_CONTEXT)).thenReturn(mockHttpContext); - when(mockHttpContext.scopes()).thenReturn(scopes); - return mockContext; - } - - public static MessagePredicate createPredicate(String config) { - return createPredicate(config, DEFAULT_USE_ACCELERATED_EXTRACTORS); - } - - public static MessagePredicate createPredicate(String config, boolean useAcceleratedExtractor) { - try { - PredicateNodeTransformer transformer = useAcceleratedExtractor - ? Transformers.PREDICATE : PredicateNodeTransformer.DEFAULT; - Predicate predicate = transformer.transform(config); - return new MessagePredicate(predicate); - } catch (Exception e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - public static void tagMessages(HttpMessage... messages) { - for (HttpMessage message : messages) { - message.setTag(TAG_SESSION_ID, "sid1"); - } - } - - public static void printErrors(Errors errors) { - List<ObjectError> allErrors = errors.getAllErrors(); - if (allErrors.size() > 0) { - System.out.println("ERRORS:"); - for (ObjectError error : allErrors) { - System.out.println(error); - } - } - } - - public static Map<String, ParametersBag> getSessions(HttpScopes scopes) { - Map<String, Map<String, ParametersBag>> zonesSessions = ReflectionUtils.<Map>getField(scopes, "zonesSessions"); - Map<String, ParametersBag> defaultZone = zonesSessions.get(ZONE_DEFAULT); - System.out.println(defaultZone); - return defaultZone; - } - -}
--- a/stress-tester/src/test/java/com/passus/st/client/filter/MatchFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.config.validation.Errors; -import com.passus.net.dns.DnsARecord; -import com.passus.net.dns.DnsRecord; -import com.passus.net.http.*; -import com.passus.st.AppUtils; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static com.passus.st.utils.Assert.assertNoError; -import static org.testng.AssertJUnit.assertEquals; -import static org.testng.AssertJUnit.assertTrue; - -/** - * @author Mirosław Hawrot - */ -public class MatchFilterTest { - - private <T> List<T> filter(List<T> messages, String config) { - MessagePredicate predicate = FilterTestUtils.createPredicate(config); - return filter(messages, predicate); - } - - private <T> List<T> filter(List<T> messages, MessagePredicate predicate) { - List<T> out = new ArrayList<>(messages.size()); - for (T message : messages) { - if (predicate.test(message)) { - out.add(message); - } - } - - return out; - } - - private List<HttpRequest> httpRequests() { - return Arrays.asList( - HttpRequestBuilder.get("http://test.com/test").header("Header", "TheValue").build(), - HttpRequestBuilder.get("http://test2.com/test2").build() - ); - } - - private List<HttpResponse> httpResponses() { - return Arrays.asList( - HttpResponseBuilder.ok().build(), - HttpResponseBuilder.status(HttpStatus.CREATED).build(), - HttpResponseBuilder.status(HttpStatus.ACCEPTED).build() - ); - } - - private List<DnsRecord> dnsRecords() { - DnsRecord dnsRecord1 = new DnsARecord(); - dnsRecord1.setName("test1.com"); - - DnsRecord dnsRecord2 = new DnsARecord(); - dnsRecord2.setName("test2.com"); - - return Arrays.asList(dnsRecord1, dnsRecord2); - } - - @BeforeClass - public static void beforeClass() { - AppUtils.registerAll(); - } - - @AfterClass - public static void afterClass() { - AppUtils.unregisterAll(); - } - - @Test - public void testHttpFilterOutbound() { - List<HttpRequest> httpRequests = httpRequests(); - List<HttpResponse> httpResponses = httpResponses(); - - List<HttpRequest> reqs; - reqs = filter(httpRequests, "{'@req.url': {$contains: \"test2\"}}"); - assertEquals(1, reqs.size()); - assertEquals("/test2", reqs.get(0).getUri().toString()); - - reqs = filter(httpRequests, "{'@req.uri': {$contains: \"test2\"}}"); - assertEquals(1, reqs.size()); - assertEquals("/test2", reqs.get(0).getUri().toString()); - - reqs = filter(httpRequests, "{\"@req.getHeader('Header')\": {$contains: \"Val\"}}"); - assertEquals(1, reqs.size()); - assertEquals("/test", reqs.get(0).getUri().toString()); - - List<HttpResponse> resps; - resps = filter(httpResponses, "{'@resp.status.code': 200}"); - assertEquals(1, resps.size()); - - resps = filter(httpResponses, "{'@resp.status.code': '200'}"); - assertEquals(1, resps.size()); - - resps = filter(httpResponses, "{'@resp.status.code': {$gt: 200}}"); - assertEquals(2, resps.size()); - - MessagePredicate predicate = FilterTestUtils.createPredicate( - "{'@resp.status.code': {$gt: 200}}", false); - resps = filter(httpResponses, predicate); - assertEquals(2, resps.size()); - } - - @Test - public void testHttpConfigureAndFilterOutbound() throws Exception { - List<HttpRequest> httpRequests = httpRequests(); - - String filterConfig = "filters:\n" - + " - type: matcher\n" - + " matches:\n" - + " '@req.uri': {$contains: 'test'}\n" - + " '@resp.status.code': 200\n"; - - Errors errors = new Errors(); - List<FlowFilter> filters = FlowFiltersConfigurator.getFilters(filterConfig, errors, null); - - assertNoError(errors); - assertEquals(1, filters.size()); - assertTrue(filters.get(0) instanceof MatchFilter); - - MatchFilter filter = (MatchFilter) filters.get(0); - MessagePredicate predicate = filter.getPredicate(); - - List<HttpRequest> res = filter(httpRequests, "{'@req.url': {$contains: \"test2\"}}"); - assertEquals(1, res.size()); - assertEquals("/test2", res.get(0).getUri().toString()); - - res = filter(httpRequests, "{'@req.uri': {$contains: \"test2\"}}"); - assertEquals(1, res.size()); - assertEquals("/test2", res.get(0).getUri().toString()); - } - - @Test - public void testDnsFilterOutbound() { - List<DnsRecord> dnsRecords = dnsRecords(); - List<DnsRecord> filtered = filter(dnsRecords, "{'@req.name': {$contains: \"test1\"}}"); - assertEquals(1, filtered.size()); - assertEquals("test1.com", filtered.get(0).getName()); - } - -}
--- a/stress-tester/src/test/java/com/passus/st/client/filter/MvelFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.commons.utils.ResourceUtils; -import com.passus.config.validation.Errors; -import com.passus.net.http.HttpMethod; -import com.passus.net.http.HttpRequest; -import com.passus.net.http.HttpRequestBuilder; -import java.io.File; -import java.util.List; - -import org.mvel2.MVEL; -import org.mvel2.compiler.ExecutableStatement; -import static org.testng.AssertJUnit.*; -import org.testng.annotations.Test; - -/** - * - * @author mikolaj.podbielski - */ -public class MvelFilterTest { - - @Test - public void testFilterOutbound() { - HttpRequest req = HttpRequestBuilder.get("http://example.com/index.html").build(); - - String expression = "$req.setMethod(com.passus.net.http.HttpMethod.HEAD);" - + "$req.getUri().toString().equals(\"/index.html\") ? 1 : 0"; - - MvelFilter filter = new MvelFilter(); - filter.setStatement(es(expression)); - - int result = filter.filterOutbound(req, null, null); - - assertEquals(1, result); - assertEquals(HttpMethod.HEAD, req.getMethod()); - } - - @Test - public void testConfigure() throws Exception { - File file = ResourceUtils.getFile("mvel/return1.mvel"); - - String filterConfig = "filters:\n" - + " - type: mvel\n" - + " dir: out\n" - + " script: return -1\n"; - - Errors errors = new Errors(); - List<FlowFilter> filters = FlowFiltersConfigurator.getFilters(filterConfig, errors, null); - FilterTestUtils.printErrors(errors); - - assertEquals(0, errors.getErrorCount()); - assertEquals(1, filters.size()); - assertTrue(filters.get(0) instanceof MvelFilter); - - MvelFilter filter = (MvelFilter) filters.get(0); - assertEquals(-1, filter.filterOutbound(null, null, null)); - assertEquals(0, filter.filterInbound(null, null, null)); - } - - public static ExecutableStatement es(String expression) { - return (ExecutableStatement) MVEL.compileExpression(expression); - } -}
--- a/stress-tester/src/test/java/com/passus/st/client/filter/SequenceFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -package com.passus.st.client.filter; - -import com.passus.commons.metric.MapMetric; -import com.passus.commons.utils.ResourceUtils; -import com.passus.config.validation.Errors; -import com.passus.filter.AndPredicate; -import com.passus.filter.BeanValueExtractor; -import com.passus.filter.ComparisonOperator; -import com.passus.filter.ComparisonPredicate; -import com.passus.filter.UnmutableValueExtractor; -import com.passus.filter.ValueExtractor; -import com.passus.filter.ValueExtractorParser; -import com.passus.filter.config.PredicateNodeTransformer; -import com.passus.net.http.HttpRequest; -import com.passus.net.http.HttpRequestBuilder; -import com.passus.net.http.HttpResponse; -import com.passus.net.http.HttpResponseBuilder; -import com.passus.st.AppUtils; -import com.passus.st.client.filter.SequenceFilter.SequenceItem; -import com.passus.st.filter.Transformers; -import java.io.File; -import java.io.Serializable; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Predicate; -import static org.testng.AssertJUnit.*; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -/** - * - * @author mikolaj.podbielski - */ -public class SequenceFilterTest { - - private static final PredicateNodeTransformer TRANSFORMER = Transformers.PREDICATE; - - @BeforeClass - public static void beforeClass() { - AppUtils.registerAll(); - } - - @AfterClass - public static void afterClass() { - AppUtils.unregisterAll(); - } - - @Test - public void testFilterInbound() throws Exception { - HttpRequest req0 = HttpRequestBuilder.get("http://example.com/res1").build(); - HttpResponse resp0 = HttpResponseBuilder.ok().cookie("id", "123").build(); - - HttpRequest req1 = HttpRequestBuilder.get("http://example.com/res2") - .cookie("id", "123").header("Xyz", "abc").build(); - HttpResponse resp1 = HttpResponseBuilder.ok().build(); - - TestSequenceListener listener = new TestSequenceListener(); - - SequenceItem[] seqItems = { - item("{\"@req.uri\": \"/res1\", \"@resp.getCookie('id')\": {$neq: \"0\"}}", 0), - item("{\"@req.getHeader('xyz')\": \"abc\", \"@req.getCookie('id')\": \"@_i0.resp.getCookie('id')\"}", 1, "last"),}; - - Map<String, ValueExtractor> values = new HashMap<>(); - values.put("code", value("@_i0.resp.status.code")); - values.put("xhost", value("@_i0.req.url.host")); - values.put("header", value("@_i1.req.getHeader('xyz')")); - values.put("cookie", value("@last.req.getCookie('id')")); - values.put("seqName", value("example sequence")); - - SequenceFilter filter = new SequenceFilter().instanceForWorker(0); - filter.setListener(listener); - filter.setSeqItems(seqItems); - filter.setValues(values); - - filter.filterInbound(req0, resp0, null); - filter.filterInbound(req1, resp1, null); - - assertEquals(1, listener.events.size()); - Map<String, Serializable> extracted = listener.events.get(0).getAttributesValue(); - assertEquals(200, extracted.get("code")); - assertEquals("example.com", extracted.get("xhost").toString()); - assertEquals("abc", extracted.get("header").toString()); - assertEquals("123", extracted.get("cookie").toString()); - assertEquals("example sequence", extracted.get("seqName").toString()); - } - - private static SequenceItem item(String predicateString, int num) throws Exception { - Predicate predicate = TRANSFORMER.transform(predicateString); - return new SequenceItem(predicate, num); - } - - private static SequenceItem item(String predicateString, int num, String alias) throws Exception { - Predicate predicate = TRANSFORMER.transform(predicateString); - SequenceItem si = new SequenceItem(predicate, num); - si.setAlias(alias); - return si; - } - - private static ValueExtractor value(String s) throws ParseException { - return ValueExtractorParser.DEFAULT.parse(s); - } - - @Test - public void testConfigure() throws Exception { - File file = ResourceUtils.getFile("com/passus/st/client/http/filter/sequence.yml"); - String filterConfig = new String(Files.readAllBytes(Paths.get(file.toURI()))); - - Errors errors = new Errors(); - List<FlowFilter> filters = FlowFiltersConfigurator.getFilters(filterConfig, errors, null); - FilterTestUtils.printErrors(errors); - - assertEquals(0, errors.getErrorCount()); - assertEquals(1, filters.size()); - assertTrue(filters.get(0) instanceof SequenceFilter); - SequenceFilter filter = (SequenceFilter) filters.get(0); - - SequenceItem[] seqItems = filter.getSeqItems(); - assertEquals(2, seqItems.length); - assertSeqItemValue(seqItems[0], 0, 10000, null); - assertSeqItemValue(seqItems[1], 1, 20000, "last"); - - AndPredicate p0 = (AndPredicate) seqItems[0].getPredicate(); - assertEquals(2, p0.getSubPredicates().size()); - ComparisonPredicate sp1 = (ComparisonPredicate) p0.getSubPredicates().get(1); - assertEquals(ComparisonOperator.NOT_EQUAL, sp1.getOperator()); - - assertEquals("resp.getCookie('id')", sp1.getFieldName()); - - UnmutableValueExtractor uve = (UnmutableValueExtractor) sp1.getPattern(); - assertEquals(123, uve.extract(null)); - - Map<String, ValueExtractor> values = filter.getValues(); - assertEquals(4, values.size()); - ValueExtractor extractor = values.get("header"); - assertTrue(extractor instanceof BeanValueExtractor); - BeanValueExtractor bve = (BeanValueExtractor) extractor; - assertEquals("last.req.getHeader('xyz')", bve.getFieldName()); - } - - private static void assertSeqItemValue(SequenceItem item, int num, long time, String alias) { - assertEquals("num", num, item.getNum()); - assertEquals("time", time, item.getTime()); - assertEquals("alias", alias, item.getAlias()); - } - - public static class TestSequenceListener implements SequenceListener { - - ArrayList<MapMetric> events = new ArrayList<>(); - - @Override - public void sequenceDetected(MapMetric sequence) { - events.add(sequence); - } - - public void reset() { - events.clear(); - } - } -}
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpBasicAuthLoginFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpBasicAuthLoginFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -11,9 +11,9 @@ import com.passus.net.http.HttpResponseBuilder; import com.passus.st.AppUtils; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FilterTestUtils; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFiltersConfigurator; +import com.passus.st.filter.FilterTestUtils; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFiltersConfigurator; import com.passus.st.client.credentials.Credentials; import com.passus.st.client.credentials.CredentialsProvider; import com.passus.st.client.credentials.CsvUsernamePasswordCredentialsProvider;
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpCsrfFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpCsrfFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -8,9 +8,9 @@ import com.passus.net.http.HttpResponseBuilder; import com.passus.st.ParametersBag; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FilterTestUtils; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFiltersConfigurator; +import com.passus.st.filter.FilterTestUtils; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFiltersConfigurator; import com.passus.st.client.http.HttpScopes; import com.passus.st.client.http.filter.HttpCsrfFilter.*; import com.passus.st.emitter.SessionInfo;
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpCsrfFormFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpCsrfFormFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -13,15 +13,15 @@ import java.io.IOException; import java.util.List; -import static com.passus.st.client.filter.FilterTestUtils.createMockContext; +import static com.passus.st.filter.FilterTestUtils.createMockContext; import static com.passus.st.client.http.filter.HttpFlowUtils.extractHttpContext; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.testng.AssertJUnit.*; -import com.passus.st.client.filter.FilterTestUtils; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFiltersConfigurator; +import com.passus.st.filter.FilterTestUtils; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFiltersConfigurator; import org.testng.annotations.Test; /**
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpDigestAuthLoginFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpDigestAuthLoginFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -15,7 +15,7 @@ import static com.passus.st.client.http.HttpConsts.PARAM_USERNAME; import static com.passus.st.client.http.HttpConsts.TAG_SESSION_ID; -import static com.passus.st.client.filter.FilterTestUtils.createMockContext; +import static com.passus.st.filter.FilterTestUtils.createMockContext; import static com.passus.st.client.http.filter.HttpFlowUtils.extractHttpContext; import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals;
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpFiltersConfiguratorTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpFiltersConfiguratorTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -3,8 +3,8 @@ import com.passus.commons.utils.ResourceUtils; import com.passus.config.ConfigurationContext; import com.passus.config.validation.Errors; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFiltersConfigurator; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFiltersConfigurator; import com.passus.st.client.credentials.MultiCredentialsProvider; import com.passus.st.client.credentials.UsernamePasswordCredentialsProvider; import java.io.File;
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpFiltersNodeDefinitionCreatorTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpFiltersNodeDefinitionCreatorTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -10,7 +10,7 @@ import com.passus.config.YamlConfigurationReader; import com.passus.config.schema.NodeDefinition; import com.passus.config.validation.Errors; -import com.passus.st.client.filter.FlowFilterNodeDefinitionCreator; +import com.passus.st.filter.FlowFilterNodeDefinitionCreator; import com.passus.st.client.http.filter.HttpMessageModificationOperations.*; import java.io.File; import java.util.List;
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpFormLoginFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpFormLoginFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -12,13 +12,13 @@ import static com.passus.st.client.http.HttpConsts.PARAM_USERNAME; import static com.passus.st.client.http.HttpConsts.TAG_SESSION_ID; -import com.passus.st.client.filter.MessagePredicate; +import com.passus.st.filter.MessagePredicate; import com.passus.st.client.http.HttpScopes; import com.passus.st.utils.TestHttpUtils; import java.io.IOException; import java.util.function.Predicate; -import static com.passus.st.client.filter.FilterTestUtils.createMockContext; +import static com.passus.st.filter.FilterTestUtils.createMockContext; import static com.passus.st.client.http.filter.HttpFlowUtils.extractHttpContext; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when;
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpHostRewriterFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpHostRewriterFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -8,8 +8,8 @@ import static com.passus.net.http.HttpHeaders.*; import com.passus.net.http.HttpRequest; import com.passus.net.http.HttpRequestBuilder; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFiltersConfigurator; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFiltersConfigurator; import com.passus.st.client.http.filter.HttpHostRewriterFilter.HostPort; import java.util.List; import java.util.Map;
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpLogoutFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpLogoutFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -7,10 +7,10 @@ import com.passus.net.http.HttpResponseBuilder; import com.passus.st.AppUtils; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FilterTestUtils; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFiltersConfigurator; -import com.passus.st.client.filter.MessagePredicate; +import com.passus.st.filter.FilterTestUtils; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFiltersConfigurator; +import com.passus.st.filter.MessagePredicate; import com.passus.st.client.http.HttpScopes; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -20,7 +20,7 @@ import static com.passus.st.client.http.HttpConsts.PARAM_USERNAME; import static com.passus.st.client.http.HttpConsts.TAG_SESSION_ID; -import static com.passus.st.client.filter.FilterTestUtils.createMockContext; +import static com.passus.st.filter.FilterTestUtils.createMockContext; import static org.testng.AssertJUnit.*; /**
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpMarkFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpMarkFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -6,9 +6,9 @@ import com.passus.st.AppUtils; import static com.passus.st.client.http.HttpConsts.TAG_MARKER; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFiltersConfigurator; -import com.passus.st.client.filter.MessagePredicate; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFiltersConfigurator; +import com.passus.st.filter.MessagePredicate; import com.passus.st.client.http.filter.HttpMarkFilter.Marker; import com.passus.st.client.http.filter.HttpMarkFilter.MarkerRule; import java.util.List;
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpMessageModificationFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpMessageModificationFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -7,10 +7,10 @@ import com.passus.net.http.*; import com.passus.st.AppUtils; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FilterTestUtils; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFiltersConfigurator; -import com.passus.st.client.filter.FilterDirection; +import com.passus.st.filter.FilterTestUtils; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFiltersConfigurator; +import com.passus.st.filter.FilterDirection; import com.passus.st.extractor.ContentExtractorUtils; import com.passus.st.client.http.filter.HttpMessageModificationOperations.*; import com.passus.st.utils.ConfigurationContextConsts;
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpMessageModificationFilterTransformerTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpMessageModificationFilterTransformerTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -8,7 +8,7 @@ import com.passus.lookup.Lookup; import com.passus.lookup.LookupList; import com.passus.lookup.filter.LookupValueExtractor; -import com.passus.st.client.filter.FilterTestUtils; +import com.passus.st.filter.FilterTestUtils; import com.passus.st.client.http.filter.HttpMessageModificationOperations.*; import com.passus.st.generator.GeneratorValueExtractor; import com.passus.st.utils.ConfigurationContextConsts;
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpMessageWrapperTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpMessageWrapperTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -1,6 +1,5 @@ package com.passus.st.client.http.filter; -import com.passus.data.ByteString; import com.passus.filter.BeanValueExtractor; import com.passus.filter.MvelValueExtractor; import com.passus.filter.UnmutableValueExtractor; @@ -12,8 +11,8 @@ import com.passus.st.AppUtils; import com.passus.st.ParametersBag; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FlowFilterFactory; -import com.passus.st.client.filter.MessageWrapper; +import com.passus.st.filter.FlowFilterFactory; +import com.passus.st.filter.MessageWrapper; import com.passus.st.client.http.HttpFlowConst; import com.passus.st.client.http.HttpFlowContext; import com.passus.st.client.http.HttpScopes;
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpScopeModificationFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpScopeModificationFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -8,9 +8,9 @@ import com.passus.net.http.HttpRequestBuilder; import com.passus.st.AppUtils; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFiltersConfigurator; -import com.passus.st.client.filter.FilterDirection; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFiltersConfigurator; +import com.passus.st.filter.FilterDirection; import com.passus.st.client.http.HttpConsts; import com.passus.st.client.http.HttpScopes; import com.passus.st.client.http.filter.HttpScopeModificationFilter.*; @@ -21,7 +21,7 @@ import java.util.Arrays; import java.util.List; -import static com.passus.st.client.filter.FilterTestUtils.createMockContext; +import static com.passus.st.filter.FilterTestUtils.createMockContext; import static com.passus.st.client.http.filter.HttpFlowUtils.extractHttpContext; import static org.testng.AssertJUnit.*;
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpSessionBlockerFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpSessionBlockerFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -6,7 +6,7 @@ import static com.passus.net.http.HttpRequestBuilder.get; import static com.passus.st.client.http.HttpConsts.TAG_SESSION_ID; -import static com.passus.st.client.filter.FilterTestUtils.createMockContext; +import static com.passus.st.filter.FilterTestUtils.createMockContext; import static com.passus.st.client.http.filter.HttpFlowUtils.extractHttpContext; import static org.testng.AssertJUnit.assertEquals;
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpSessionCookieFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpSessionCookieFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -11,7 +11,7 @@ import com.passus.st.client.FlowContext; -import static com.passus.st.client.filter.FilterTestUtils.createMockContext; +import static com.passus.st.filter.FilterTestUtils.createMockContext; import static com.passus.st.client.http.filter.HttpFlowUtils.extractHttpContext; import static com.passus.st.utils.TestHttpUtils.*; import java.util.Arrays; @@ -20,9 +20,9 @@ import static org.mockito.Mockito.when; import static org.testng.Assert.*; -import com.passus.st.client.filter.FilterTestUtils; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFiltersConfigurator; +import com.passus.st.filter.FilterTestUtils; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFiltersConfigurator; import org.testng.annotations.Test; /**
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpZoneFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpZoneFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -8,9 +8,9 @@ import com.passus.st.AppUtils; import static com.passus.st.client.http.HttpConsts.TAG_ZONE; -import com.passus.st.client.filter.FilterTestUtils; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFiltersConfigurator; +import com.passus.st.filter.FilterTestUtils; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFiltersConfigurator; import com.passus.st.client.http.filter.HttpZoneFilter.Rule; import java.util.List; import static org.testng.AssertJUnit.assertEquals;
--- a/stress-tester/src/test/java/com/passus/st/client/netflow/filter/NetflowVersionFilterTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/client/netflow/filter/NetflowVersionFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -2,8 +2,8 @@ import com.passus.config.NodeException; import com.passus.config.validation.Errors; -import com.passus.st.client.filter.FlowFilter; -import com.passus.st.client.filter.FlowFiltersConfigurator; +import com.passus.st.filter.FlowFilter; +import com.passus.st.filter.FlowFiltersConfigurator; import org.testng.annotations.Test; import java.io.IOException;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/test/java/com/passus/st/filter/CounterFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,76 @@ +package com.passus.st.filter; + +import com.passus.config.validation.Errors; +import com.passus.filter.AndPredicate; +import com.passus.filter.ComparisonOperator; +import com.passus.filter.ComparisonPredicate; +import com.passus.net.http.*; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertTrue; + +public class CounterFilterTest { + + @Test + public void testFilterInbound() { + HttpRequest req = HttpRequestBuilder.get("http://example.com").build(); + HttpResponse resp = HttpResponseBuilder.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); + + TestListener listener = new TestListener(); + + MessagePredicate predicate = FilterTestUtils.createPredicate("{'@resp.status.code': 500}"); + CounterFilter filter = new CounterFilter(); + filter.setLimit(2); + filter.setName("filter status code 500"); + filter.setPredicate(predicate); + filter.setListener(listener); + + filter.filterInbound(req, resp, null); + assertEquals(0, listener.events.size()); + filter.filterInbound(req, resp, null); + assertEquals(1, listener.events.size()); + } + + @Test + public void testConfigure() throws Exception { + String filterConfig = "filters:\n" + + " - type: counter\n" + + " name: 'filter x'\n" + + " limit: 3\n" + + " applyIf: {'@resp.status.code': 404}\n"; + + Errors errors = new Errors(); + List<FlowFilter> filters = FlowFiltersConfigurator.getFilters(filterConfig, errors, null); + FilterTestUtils.printErrors(errors); + + assertEquals(0, errors.getErrorCount()); + assertEquals(1, filters.size()); + assertTrue(filters.get(0) instanceof CounterFilter); + + CounterFilter filter = (CounterFilter) filters.get(0); + assertEquals(3, filter.getLimit()); + assertEquals("filter x", filter.getName()); + + AndPredicate<? extends Object> andPredicate = (AndPredicate) filter.getPredicate().getPredicate(); + assertEquals(1, andPredicate.getSubPredicates().size()); + ComparisonPredicate predicate = (ComparisonPredicate) andPredicate.getSubPredicates().get(0); + assertEquals("resp.status.code", predicate.getFieldName()); + assertEquals(ComparisonOperator.EQUAL, predicate.getOperator()); + } + + private static class TestListener implements CounterListener { + + private final ArrayList<Event> events = new ArrayList<>(); + + @Override + public void limitReached(Event event) { + events.add(event); + } + + } + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/test/java/com/passus/st/filter/FilterTestUtils.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,82 @@ +package com.passus.st.filter; + +import com.passus.commons.utils.ReflectionUtils; +import com.passus.config.validation.Errors; +import com.passus.config.validation.ObjectError; +import com.passus.filter.config.PredicateNodeTransformer; +import com.passus.net.http.HttpMessage; +import com.passus.st.ParametersBag; +import static com.passus.st.client.http.HttpConsts.TAG_SESSION_ID; +import static com.passus.st.client.http.HttpConsts.ZONE_DEFAULT; + +import com.passus.st.client.FlowContext; +import com.passus.st.filter.MessagePredicate; +import com.passus.st.client.http.HttpFlowConst; +import com.passus.st.client.http.HttpFlowContext; +import com.passus.st.client.http.HttpScopes; +import com.passus.st.filter.Transformers; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * + * @author mikolaj.podbielski + */ +public class FilterTestUtils { + + private static final boolean DEFAULT_USE_ACCELERATED_EXTRACTORS = true; + + public static FlowContext createMockContext() { + return createMockContext(new HttpScopes()); + } + + public static FlowContext createMockContext(HttpScopes scopes) { + FlowContext mockContext = mock(FlowContext.class); + HttpFlowContext mockHttpContext = mock(HttpFlowContext.class); + when(mockContext.getParamValue(HttpFlowConst.PARAM_HTTP_CONTEXT)).thenReturn(mockHttpContext); + when(mockHttpContext.scopes()).thenReturn(scopes); + return mockContext; + } + + public static MessagePredicate createPredicate(String config) { + return createPredicate(config, DEFAULT_USE_ACCELERATED_EXTRACTORS); + } + + public static MessagePredicate createPredicate(String config, boolean useAcceleratedExtractor) { + try { + PredicateNodeTransformer transformer = useAcceleratedExtractor + ? Transformers.PREDICATE : PredicateNodeTransformer.DEFAULT; + Predicate predicate = transformer.transform(config); + return new MessagePredicate(predicate); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + public static void tagMessages(HttpMessage... messages) { + for (HttpMessage message : messages) { + message.setTag(TAG_SESSION_ID, "sid1"); + } + } + + public static void printErrors(Errors errors) { + List<ObjectError> allErrors = errors.getAllErrors(); + if (allErrors.size() > 0) { + System.out.println("ERRORS:"); + for (ObjectError error : allErrors) { + System.out.println(error); + } + } + } + + public static Map<String, ParametersBag> getSessions(HttpScopes scopes) { + Map<String, Map<String, ParametersBag>> zonesSessions = ReflectionUtils.<Map>getField(scopes, "zonesSessions"); + Map<String, ParametersBag> defaultZone = zonesSessions.get(ZONE_DEFAULT); + System.out.println(defaultZone); + return defaultZone; + } + +}
--- a/stress-tester/src/test/java/com/passus/st/filter/HttpMessageValueExtractorTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/filter/HttpMessageValueExtractorTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -4,12 +4,9 @@ import com.passus.net.http.*; import com.passus.st.ParametersBag; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FlowFilterFactory; -import com.passus.st.client.filter.MessageWrapper; import com.passus.st.client.http.HttpFlowConst; import com.passus.st.client.http.HttpFlowContext; import com.passus.st.client.http.HttpScopes; -import com.passus.st.client.http.filter.HttpMessageWrapper; import org.testng.annotations.DataProvider; import org.testng.annotations.Test;
--- a/stress-tester/src/test/java/com/passus/st/filter/HttpMessageWrapperDynamicExtractorTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/filter/HttpMessageWrapperDynamicExtractorTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -8,9 +8,6 @@ import com.passus.net.http.HttpStatus; import static com.passus.st.client.http.HttpConsts.TAG_SESSION_ID; -import com.passus.st.client.filter.FlowFilterFactory; -import com.passus.st.client.filter.MessageWrapper; -import com.passus.st.client.http.filter.HttpMessageWrapper; import static com.passus.st.utils.Assert.*; import org.testng.annotations.Test;
--- a/stress-tester/src/test/java/com/passus/st/filter/HttpMessageWrapperStaticExtractorTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/filter/HttpMessageWrapperStaticExtractorTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -5,7 +5,6 @@ import com.passus.net.http.HttpResponse; import com.passus.net.http.HttpResponseBuilder; import com.passus.st.client.FlowContext; -import com.passus.st.client.filter.FlowFilterFactory; import com.passus.st.client.http.HttpConsts; import com.passus.st.client.http.HttpFlowConst; import com.passus.st.client.http.HttpFlowContext;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/test/java/com/passus/st/filter/MatchFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,147 @@ +package com.passus.st.filter; + +import com.passus.config.validation.Errors; +import com.passus.net.dns.DnsARecord; +import com.passus.net.dns.DnsRecord; +import com.passus.net.http.*; +import com.passus.st.AppUtils; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static com.passus.st.utils.Assert.assertNoError; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertTrue; + +/** + * @author Mirosław Hawrot + */ +public class MatchFilterTest { + + private <T> List<T> filter(List<T> messages, String config) { + MessagePredicate predicate = FilterTestUtils.createPredicate(config); + return filter(messages, predicate); + } + + private <T> List<T> filter(List<T> messages, MessagePredicate predicate) { + List<T> out = new ArrayList<>(messages.size()); + for (T message : messages) { + if (predicate.test(message)) { + out.add(message); + } + } + + return out; + } + + private List<HttpRequest> httpRequests() { + return Arrays.asList( + HttpRequestBuilder.get("http://test.com/test").header("Header", "TheValue").build(), + HttpRequestBuilder.get("http://test2.com/test2").build() + ); + } + + private List<HttpResponse> httpResponses() { + return Arrays.asList( + HttpResponseBuilder.ok().build(), + HttpResponseBuilder.status(HttpStatus.CREATED).build(), + HttpResponseBuilder.status(HttpStatus.ACCEPTED).build() + ); + } + + private List<DnsRecord> dnsRecords() { + DnsRecord dnsRecord1 = new DnsARecord(); + dnsRecord1.setName("test1.com"); + + DnsRecord dnsRecord2 = new DnsARecord(); + dnsRecord2.setName("test2.com"); + + return Arrays.asList(dnsRecord1, dnsRecord2); + } + + @BeforeClass + public static void beforeClass() { + AppUtils.registerAll(); + } + + @AfterClass + public static void afterClass() { + AppUtils.unregisterAll(); + } + + @Test + public void testHttpFilterOutbound() { + List<HttpRequest> httpRequests = httpRequests(); + List<HttpResponse> httpResponses = httpResponses(); + + List<HttpRequest> reqs; + reqs = filter(httpRequests, "{'@req.url': {$contains: \"test2\"}}"); + assertEquals(1, reqs.size()); + assertEquals("/test2", reqs.get(0).getUri().toString()); + + reqs = filter(httpRequests, "{'@req.uri': {$contains: \"test2\"}}"); + assertEquals(1, reqs.size()); + assertEquals("/test2", reqs.get(0).getUri().toString()); + + reqs = filter(httpRequests, "{\"@req.getHeader('Header')\": {$contains: \"Val\"}}"); + assertEquals(1, reqs.size()); + assertEquals("/test", reqs.get(0).getUri().toString()); + + List<HttpResponse> resps; + resps = filter(httpResponses, "{'@resp.status.code': 200}"); + assertEquals(1, resps.size()); + + resps = filter(httpResponses, "{'@resp.status.code': '200'}"); + assertEquals(1, resps.size()); + + resps = filter(httpResponses, "{'@resp.status.code': {$gt: 200}}"); + assertEquals(2, resps.size()); + + MessagePredicate predicate = FilterTestUtils.createPredicate( + "{'@resp.status.code': {$gt: 200}}", false); + resps = filter(httpResponses, predicate); + assertEquals(2, resps.size()); + } + + @Test + public void testHttpConfigureAndFilterOutbound() throws Exception { + List<HttpRequest> httpRequests = httpRequests(); + + String filterConfig = "filters:\n" + + " - type: matcher\n" + + " matches:\n" + + " '@req.uri': {$contains: 'test'}\n" + + " '@resp.status.code': 200\n"; + + Errors errors = new Errors(); + List<FlowFilter> filters = FlowFiltersConfigurator.getFilters(filterConfig, errors, null); + + assertNoError(errors); + assertEquals(1, filters.size()); + assertTrue(filters.get(0) instanceof MatchFilter); + + MatchFilter filter = (MatchFilter) filters.get(0); + MessagePredicate predicate = filter.getPredicate(); + + List<HttpRequest> res = filter(httpRequests, "{'@req.url': {$contains: \"test2\"}}"); + assertEquals(1, res.size()); + assertEquals("/test2", res.get(0).getUri().toString()); + + res = filter(httpRequests, "{'@req.uri': {$contains: \"test2\"}}"); + assertEquals(1, res.size()); + assertEquals("/test2", res.get(0).getUri().toString()); + } + + @Test + public void testDnsFilterOutbound() { + List<DnsRecord> dnsRecords = dnsRecords(); + List<DnsRecord> filtered = filter(dnsRecords, "{'@req.name': {$contains: \"test1\"}}"); + assertEquals(1, filtered.size()); + assertEquals("test1.com", filtered.get(0).getName()); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/test/java/com/passus/st/filter/MvelFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,63 @@ +package com.passus.st.filter; + +import com.passus.commons.utils.ResourceUtils; +import com.passus.config.validation.Errors; +import com.passus.net.http.HttpMethod; +import com.passus.net.http.HttpRequest; +import com.passus.net.http.HttpRequestBuilder; +import java.io.File; +import java.util.List; + +import org.mvel2.MVEL; +import org.mvel2.compiler.ExecutableStatement; +import static org.testng.AssertJUnit.*; +import org.testng.annotations.Test; + +/** + * + * @author mikolaj.podbielski + */ +public class MvelFilterTest { + + @Test + public void testFilterOutbound() { + HttpRequest req = HttpRequestBuilder.get("http://example.com/index.html").build(); + + String expression = "$req.setMethod(com.passus.net.http.HttpMethod.HEAD);" + + "$req.getUri().toString().equals(\"/index.html\") ? 1 : 0"; + + MvelFilter filter = new MvelFilter(); + filter.setStatement(es(expression)); + + int result = filter.filterOutbound(req, null, null); + + assertEquals(1, result); + assertEquals(HttpMethod.HEAD, req.getMethod()); + } + + @Test + public void testConfigure() throws Exception { + File file = ResourceUtils.getFile("mvel/return1.mvel"); + + String filterConfig = "filters:\n" + + " - type: mvel\n" + + " dir: out\n" + + " script: return -1\n"; + + Errors errors = new Errors(); + List<FlowFilter> filters = FlowFiltersConfigurator.getFilters(filterConfig, errors, null); + FilterTestUtils.printErrors(errors); + + assertEquals(0, errors.getErrorCount()); + assertEquals(1, filters.size()); + assertTrue(filters.get(0) instanceof MvelFilter); + + MvelFilter filter = (MvelFilter) filters.get(0); + assertEquals(-1, filter.filterOutbound(null, null, null)); + assertEquals(0, filter.filterInbound(null, null, null)); + } + + public static ExecutableStatement es(String expression) { + return (ExecutableStatement) MVEL.compileExpression(expression); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/test/java/com/passus/st/filter/SequenceFilterTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -0,0 +1,165 @@ +package com.passus.st.filter; + +import com.passus.commons.metric.MapMetric; +import com.passus.commons.utils.ResourceUtils; +import com.passus.config.validation.Errors; +import com.passus.filter.AndPredicate; +import com.passus.filter.BeanValueExtractor; +import com.passus.filter.ComparisonOperator; +import com.passus.filter.ComparisonPredicate; +import com.passus.filter.UnmutableValueExtractor; +import com.passus.filter.ValueExtractor; +import com.passus.filter.ValueExtractorParser; +import com.passus.filter.config.PredicateNodeTransformer; +import com.passus.net.http.HttpRequest; +import com.passus.net.http.HttpRequestBuilder; +import com.passus.net.http.HttpResponse; +import com.passus.net.http.HttpResponseBuilder; +import com.passus.st.AppUtils; +import com.passus.st.filter.SequenceFilter.SequenceItem; + +import java.io.File; +import java.io.Serializable; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; +import static org.testng.AssertJUnit.*; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * + * @author mikolaj.podbielski + */ +public class SequenceFilterTest { + + private static final PredicateNodeTransformer TRANSFORMER = Transformers.PREDICATE; + + @BeforeClass + public static void beforeClass() { + AppUtils.registerAll(); + } + + @AfterClass + public static void afterClass() { + AppUtils.unregisterAll(); + } + + @Test + public void testFilterInbound() throws Exception { + HttpRequest req0 = HttpRequestBuilder.get("http://example.com/res1").build(); + HttpResponse resp0 = HttpResponseBuilder.ok().cookie("id", "123").build(); + + HttpRequest req1 = HttpRequestBuilder.get("http://example.com/res2") + .cookie("id", "123").header("Xyz", "abc").build(); + HttpResponse resp1 = HttpResponseBuilder.ok().build(); + + TestSequenceListener listener = new TestSequenceListener(); + + SequenceItem[] seqItems = { + item("{\"@req.uri\": \"/res1\", \"@resp.getCookie('id')\": {$neq: \"0\"}}", 0), + item("{\"@req.getHeader('xyz')\": \"abc\", \"@req.getCookie('id')\": \"@_i0.resp.getCookie('id')\"}", 1, "last"),}; + + Map<String, ValueExtractor> values = new HashMap<>(); + values.put("code", value("@_i0.resp.status.code")); + values.put("xhost", value("@_i0.req.url.host")); + values.put("header", value("@_i1.req.getHeader('xyz')")); + values.put("cookie", value("@last.req.getCookie('id')")); + values.put("seqName", value("example sequence")); + + SequenceFilter filter = new SequenceFilter().instanceForWorker(0); + filter.setListener(listener); + filter.setSeqItems(seqItems); + filter.setValues(values); + + filter.filterInbound(req0, resp0, null); + filter.filterInbound(req1, resp1, null); + + assertEquals(1, listener.events.size()); + Map<String, Serializable> extracted = listener.events.get(0).getAttributesValue(); + assertEquals(200, extracted.get("code")); + assertEquals("example.com", extracted.get("xhost").toString()); + assertEquals("abc", extracted.get("header").toString()); + assertEquals("123", extracted.get("cookie").toString()); + assertEquals("example sequence", extracted.get("seqName").toString()); + } + + private static SequenceItem item(String predicateString, int num) throws Exception { + Predicate predicate = TRANSFORMER.transform(predicateString); + return new SequenceItem(predicate, num); + } + + private static SequenceItem item(String predicateString, int num, String alias) throws Exception { + Predicate predicate = TRANSFORMER.transform(predicateString); + SequenceItem si = new SequenceItem(predicate, num); + si.setAlias(alias); + return si; + } + + private static ValueExtractor value(String s) throws ParseException { + return ValueExtractorParser.DEFAULT.parse(s); + } + + @Test + public void testConfigure() throws Exception { + File file = ResourceUtils.getFile("com/passus/st/client/http/filter/sequence.yml"); + String filterConfig = new String(Files.readAllBytes(Paths.get(file.toURI()))); + + Errors errors = new Errors(); + List<FlowFilter> filters = FlowFiltersConfigurator.getFilters(filterConfig, errors, null); + FilterTestUtils.printErrors(errors); + + assertEquals(0, errors.getErrorCount()); + assertEquals(1, filters.size()); + assertTrue(filters.get(0) instanceof SequenceFilter); + SequenceFilter filter = (SequenceFilter) filters.get(0); + + SequenceItem[] seqItems = filter.getSeqItems(); + assertEquals(2, seqItems.length); + assertSeqItemValue(seqItems[0], 0, 10000, null); + assertSeqItemValue(seqItems[1], 1, 20000, "last"); + + AndPredicate p0 = (AndPredicate) seqItems[0].getPredicate(); + assertEquals(2, p0.getSubPredicates().size()); + ComparisonPredicate sp1 = (ComparisonPredicate) p0.getSubPredicates().get(1); + assertEquals(ComparisonOperator.NOT_EQUAL, sp1.getOperator()); + + assertEquals("resp.getCookie('id')", sp1.getFieldName()); + + UnmutableValueExtractor uve = (UnmutableValueExtractor) sp1.getPattern(); + assertEquals(123, uve.extract(null)); + + Map<String, ValueExtractor> values = filter.getValues(); + assertEquals(4, values.size()); + ValueExtractor extractor = values.get("header"); + assertTrue(extractor instanceof BeanValueExtractor); + BeanValueExtractor bve = (BeanValueExtractor) extractor; + assertEquals("last.req.getHeader('xyz')", bve.getFieldName()); + } + + private static void assertSeqItemValue(SequenceItem item, int num, long time, String alias) { + assertEquals("num", num, item.getNum()); + assertEquals("time", time, item.getTime()); + assertEquals("alias", alias, item.getAlias()); + } + + public static class TestSequenceListener implements SequenceListener { + + ArrayList<MapMetric> events = new ArrayList<>(); + + @Override + public void sequenceDetected(MapMetric sequence) { + events.add(sequence); + } + + public void reset() { + events.clear(); + } + } +}
--- a/stress-tester/src/test/java/com/passus/st/vars/VarsConfiguratorTest.java Wed Mar 25 14:01:15 2020 +0100 +++ b/stress-tester/src/test/java/com/passus/st/vars/VarsConfiguratorTest.java Thu Mar 26 13:27:52 2020 +0100 @@ -7,7 +7,7 @@ import com.passus.filter.ValueExtractor; import com.passus.net.http.HttpRequest; import com.passus.net.http.HttpRequestBuilder; -import com.passus.st.client.filter.FlowFilterFactory; +import com.passus.st.filter.FlowFilterFactory; import com.passus.st.client.http.filter.HttpMessageWrapper; import com.passus.st.filter.HttpMessageWrapperDynamicExtractor; import org.testng.annotations.Test;