Mercurial > stress-tester
changeset 525:924eac805b34
HttpZoneFilter
author | Devel 2 |
---|---|
date | Tue, 29 Aug 2017 12:45:02 +0200 |
parents | 73fa34b62fa1 |
children | c72b7f546870 |
files | stress-tester/src/main/java/com/passus/st/client/http/filter/HttpZoneFilter.java stress-tester/src/test/java/com/passus/st/client/http/filter/HttpZoneFilterTest.java |
diffstat | 2 files changed, 287 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpZoneFilter.java Tue Aug 29 12:45:02 2017 +0200 @@ -0,0 +1,198 @@ +package com.passus.st.client.http.filter; + +import com.passus.commons.Assert; +import com.passus.commons.annotations.Plugin; +import com.passus.commons.utils.ArrayUtils; +import com.passus.config.CListNode; +import com.passus.config.CMapNode; +import com.passus.config.CNode; +import com.passus.config.CTupleNode; +import com.passus.config.CValueNode; +import com.passus.config.Configuration; +import com.passus.config.NodeConversionException; +import com.passus.config.annotations.NodeDefinitionCreate; +import static com.passus.config.schema.ConfigurationSchemaBuilder.mapDef; +import static com.passus.config.schema.ConfigurationSchemaBuilder.tupleDef; +import com.passus.config.schema.NodeDefinition; +import com.passus.config.schema.NodeDefinitionCreator; +import com.passus.config.validation.Errors; +import static com.passus.config.validation.ValidationDefaultMessages.GENERAL_CONVERSION_ERROR; +import com.passus.filter.config.PredicateNodeTransformer; +import com.passus.net.http.HttpRequest; +import com.passus.net.http.HttpResponse; +import static com.passus.st.client.http.HttpConsts.TAG_ZONE; +import com.passus.st.client.http.HttpFlowContext; +import com.passus.st.plugin.PluginConstants; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; + +/** + * + * @author Mirosław Hawrot + */ +@NodeDefinitionCreate(HttpZoneFilter.HttpZoneFilterNodeDefCreator.class) +@Plugin(name = HttpZoneFilter.TYPE, category = PluginConstants.CATEGORY_HTTP_FILTER) +public class HttpZoneFilter extends HttpFilter { + + public static final String TYPE = "zone"; + + public static class Rule { + + private final String zone; + + private final HttpMessagePredicate predicate; + + public Rule(String zone, HttpMessagePredicate predicate) { + Assert.notNull(zone, "zone"); + Assert.notNull(predicate, "predicate"); + this.zone = zone; + this.predicate = predicate; + } + + public String getZone() { + return zone; + } + + public boolean match(HttpRequest req, HttpResponse resp, HttpFlowContext context) { + return predicate.test(new HttpMessageWrapper(req, resp, context)); + } + + } + + private final List<Rule> rules = new ArrayList<>(); + + public HttpZoneFilter() { + } + + public HttpZoneFilter(List<Rule> rules) { + Assert.notContainsNull(rules, "rules"); + this.rules.addAll(rules); + } + + public void addRule(Rule rule) { + Assert.notNull(rule, "rule"); + rules.add(rule); + } + + public List<Rule> getRules() { + return Collections.unmodifiableList(rules); + } + + @Override + public void configure(Configuration config) { + List<Rule> cfgRules = (List<Rule>) config.get("zones", Collections.EMPTY_LIST); + rules.clear(); + rules.addAll(cfgRules); + } + + @Override + public int filterOutbound(HttpRequest req, HttpResponse resp, HttpFlowContext context) { + if (req != null && !rules.isEmpty()) { + for (Rule rule : rules) { + if (rule.match(req, resp, context)) { + req.setTag(TAG_ZONE, rule.zone); + if (resp != null) { + resp.setTag(TAG_ZONE, rule.zone); + } + break; + } + } + } + + return DUNNO; + } + + @Override + public int filterInbound(HttpRequest req, HttpResponse resp, HttpFlowContext context) { + if (req != null && resp != null) { + String zone = (String) req.getTag(TAG_ZONE); + if (zone != null) { + resp.setTag(TAG_ZONE, zone); + } + } + + return DUNNO; + } + + @Override + public HttpFilter instanceForWorker(int index) { + return new HttpZoneFilter(rules); + } + + public static class HttpZoneFilterNodeDefCreator implements NodeDefinitionCreator { + + @Override + public NodeDefinition create() { + return mapDef( + tupleDef("zones", new HttpZoneFilterRuleNodeDefinition()) + ); + } + + } + + public static class HttpZoneFilterRuleNodeDefinition extends NodeDefinition<HttpZoneFilterRuleNodeDefinition> { + + private final static Set<Class<? extends CNode>> SUPPORTED = ArrayUtils.asUnmodifiableSet(CMapNode.class); + + private static final PredicateNodeTransformer TRANSFORMER = new PredicateNodeTransformer(); + + @Override + public Set<Class<? extends CNode>> getSupportedNode() { + return SUPPORTED; + } + + @Override + protected void doValidate(CNode node, Errors errors) { + CMapNode mapNode = (CMapNode) node; + for (CTupleNode tuple : mapNode.getChildren()) { + try { + errors.pushNestedPath(tuple.getName()); + + } finally { + errors.popNestedPath(); + } + } + } + + @Override + protected CNode doTransform(CNode node, Errors errors, boolean reverse) { + if (!reverse) { + CMapNode mapNode = (CMapNode) node; + CListNode listNode = new CListNode(); + + for (CTupleNode tuple : mapNode.getChildren()) { + try { + errors.pushNestedPath(tuple.getName()); + + try { + Predicate predicate = TRANSFORMER.transform(tuple.getNode()); + HttpMessagePredicate msgPredicate = new HttpMessagePredicate(predicate); + CValueNode valNode = new CValueNode(new Rule(tuple.getName(), msgPredicate)); + listNode.add(valNode); + } catch (NodeConversionException ex) { + errors.reject(node, ex.getMessage()); + } catch (Exception e) { + errors.reject(tuple.getNode(), GENERAL_CONVERSION_ERROR); + } + + } catch (Exception e) { + errors.popNestedPath(); + } + } + + return listNode; + } else { + throw new UnsupportedOperationException("Not supported yet."); + } + } + + @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/test/java/com/passus/st/client/http/filter/HttpZoneFilterTest.java Tue Aug 29 12:45:02 2017 +0200 @@ -0,0 +1,89 @@ +package com.passus.st.client.http.filter; + +import com.passus.config.validation.Errors; +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 static com.passus.st.client.http.HttpConsts.TAG_ZONE; +import com.passus.st.client.http.HttpFlowContext; +import com.passus.st.client.http.filter.HttpZoneFilter.Rule; +import java.util.List; +import java.util.function.Predicate; +import static org.testng.Assert.*; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertTrue; +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * + * @author Mirosław Hawrot + */ +public class HttpZoneFilterTest { + + private final PredicateNodeTransformer nodeTransformer = new PredicateNodeTransformer(); + + @BeforeClass + public static void beforeClass() { + AppUtils.registerAll(); + } + + @AfterClass + public static void afterClass() { + AppUtils.unregisterAll(); + } + + private HttpMessagePredicate predicate(String config) { + try { + Predicate predicate = nodeTransformer.transform(config); + return new HttpMessagePredicate(predicate); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Test + public void testFilter() { + HttpRequest req = HttpRequestBuilder.get("http://test.com/test").build(); + HttpResponse respOut = HttpResponseBuilder.ok().build(); + HttpResponse respIn = HttpResponseBuilder.ok().build(); + + HttpZoneFilter filter = new HttpZoneFilter(); + filter.addRule(new Rule("testZone", predicate("{req.url: {$contains: \"test\"}}"))); + + filter.filterOutbound(req, respOut, null); + filter.filterInbound(req, respIn, null); + + assertEquals("testZone", req.getTag(TAG_ZONE)); + assertEquals("testZone", respOut.getTag(TAG_ZONE)); + assertEquals("testZone", respIn.getTag(TAG_ZONE)); + } + + @Test + public void testConfigure() throws Exception { + String filterConfig = "filters:\n" + + " - type: zone\n" + + " zones:\n" + + " \"zone1\": {req.url: {$contains: \"test\"}}\n"; + + Errors errors = new Errors(); + List<HttpFilter> filters = HttpFiltersConfigurator.getFilters(filterConfig, errors); + + assertEquals(0, errors.getErrorCount()); + assertEquals(1, filters.size()); + assertTrue(filters.get(0) instanceof HttpZoneFilter); + + HttpZoneFilter zoneFilter = (HttpZoneFilter) filters.get(0); + List<Rule> rules = zoneFilter.getRules(); + assertEquals(1, rules.size()); + + Rule rule = rules.get(0); + assertEquals("zone1", rule.getZone()); + } +}