Mercurial > stress-tester
changeset 464:fa4e311fdf65
HttpScopeModificationFilter in progress
author | Devel 2 |
---|---|
date | Wed, 02 Aug 2017 14:51:49 +0200 |
parents | a98b900ee048 |
children | 5401dadf33bb |
files | stress-tester/src/main/java/com/passus/st/client/http/HttpScopes.java stress-tester/src/main/java/com/passus/st/client/http/filter/HttpFiltersUtils.java stress-tester/src/main/java/com/passus/st/client/http/filter/HttpScopeModificationFilter.java stress-tester/src/main/java/com/passus/st/client/http/filter/HttpScopeModificationFilterTransformer.java stress-tester/src/main/java/com/passus/st/config/HeaderOperationNodeDefinition.java stress-tester/src/test/java/com/passus/st/client/http/filter/HttpScopeModificationFilterTest.java |
diffstat | 6 files changed, 483 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/stress-tester/src/main/java/com/passus/st/client/http/HttpScopes.java Wed Aug 02 14:50:37 2017 +0200 +++ b/stress-tester/src/main/java/com/passus/st/client/http/HttpScopes.java Wed Aug 02 14:51:49 2017 +0200 @@ -75,6 +75,19 @@ return false; } + public boolean removeSession(HttpMessage msg) { + String zone = (String) msg.getTag(TAG_ZONE, ZONE_DEFAULT); + Map<String, ParametersBag> zoneSessions = getZoneSessions(zone, false); + if (zoneSessions != null) { + String sessionId = (String) msg.getTag(TAG_SESSION_ID); + if (sessionId != null) { + return (zoneSessions.remove(sessionId) != null); + } + } + + return false; + } + public ParametersBag getSession(String sessionId) { return HttpScopes.this.getSession(sessionId, ZONE_DEFAULT); } @@ -83,6 +96,10 @@ return HttpScopes.this.getSession(sessionId, zone, true); } + public ParametersBag getSession(String sessionId, boolean autocreate) { + return HttpScopes.this.getSession(sessionId, ZONE_DEFAULT, autocreate); + } + public ParametersBag getSession(String sessionId, String zone, boolean autocreate) { Map<String, ParametersBag> zoneSessions = getZoneSessions(zone, autocreate); if (zoneSessions == null) { @@ -112,6 +129,15 @@ return getSession(sessionId, zone, autocreate); } + public ParametersBag getSession(HttpMessage msg, String zone, boolean autocreate) { + String sessionId = (String) msg.getTag(TAG_SESSION_ID); + if (sessionId == null) { + return null; + } + + return getSession(sessionId, zone, autocreate); + } + public boolean removeConversation(HttpRequest req) { String zone = (String) req.getTag(TAG_ZONE, ZONE_DEFAULT); return removeConversation(req.getId(), zone);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpFiltersUtils.java Wed Aug 02 14:51:49 2017 +0200 @@ -0,0 +1,30 @@ +package com.passus.st.client.http.filter; + +import com.passus.filter.UnmutableValueExtractor; +import com.passus.filter.ValueExtractor; +import com.passus.net.http.HttpRequest; +import com.passus.net.http.HttpResponse; +import com.passus.st.client.http.HttpFlowContext; + +/** + * + * @author Mirosław Hawrot + */ +public class HttpFiltersUtils { + + private HttpFiltersUtils() { + } + + public static Object extractValue(ValueExtractor extractor, HttpRequest req, HttpResponse resp, HttpFlowContext context) { + Object value; + if (extractor instanceof UnmutableValueExtractor) { + value = extractor.extract(null); + } else { + HttpMessageWrapper wrapper = new HttpMessageWrapper(req, resp, context); + value = extractor.extract(wrapper); + } + + return value; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpScopeModificationFilter.java Wed Aug 02 14:51:49 2017 +0200 @@ -0,0 +1,201 @@ +package com.passus.st.client.http.filter; + +import com.passus.commons.Assert; +import com.passus.commons.annotations.Plugin; +import com.passus.config.Configuration; +import com.passus.config.annotations.NodeDefinitionCreate; +import static com.passus.config.schema.ConfigurationSchemaBuilder.mapDef; +import static com.passus.config.schema.ConfigurationSchemaBuilder.nullValueDef; +import static com.passus.config.schema.ConfigurationSchemaBuilder.tupleDef; +import static com.passus.config.schema.ConfigurationSchemaBuilder.valueDef; +import static com.passus.config.schema.ConfigurationSchemaBuilder.valueDefBool; +import com.passus.config.schema.KeyNameVaryListNodeDefinition; +import com.passus.config.schema.NodeDefinition; +import com.passus.config.schema.NodeDefinitionCreator; +import com.passus.filter.ValueExtractor; +import com.passus.net.http.HttpRequest; +import com.passus.net.http.HttpResponse; +import com.passus.st.ParametersBag; +import com.passus.st.client.http.HttpFlowContext; +import com.passus.st.config.HeaderOperationNodeDefinition; +import com.passus.st.plugin.PluginConstants; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Mirosław Hawrot + */ +@NodeDefinitionCreate(HttpScopeModificationFilter.HttpScopeModificationFilterNodeDefCreator.class) +@Plugin(name = HttpScopeModificationFilter.TYPE, category = PluginConstants.CATEGORY_HTTP_FILTER) +public class HttpScopeModificationFilter extends HttpFilter { + + public static final String TYPE = "modifyScope"; + + public static abstract class Operation { + + public abstract void process(HttpRequest req, HttpResponse resp, HttpFlowContext context); + + } + + public static class RemoveSessionOperation extends Operation { + + @Override + public void process(HttpRequest req, HttpResponse resp, HttpFlowContext context) { + context.scopes().removeSession(req); + } + + } + + public static class RemoveSessionParamOperation extends Operation { + + private final String paramName; + + public RemoveSessionParamOperation(String paramName) { + Assert.notNull(paramName, "paramName"); + this.paramName = paramName; + } + + @Override + public void process(HttpRequest req, HttpResponse resp, HttpFlowContext context) { + ParametersBag params = context.scopes().getSession(req, false); + if (params != null) { + params.remove(paramName); + } + } + + } + + public static class SetSessionParamOperation extends Operation { + + protected final boolean autocreate; + + protected final String paramName; + + protected final ValueExtractor valueExtractor; + + protected final boolean checkValueExists; + + public SetSessionParamOperation(String paramName, ValueExtractor valueExtractor) { + this(paramName, valueExtractor, true); + } + + public SetSessionParamOperation(String paramName, ValueExtractor valueExtractor, boolean checkValueExists) { + this(paramName, valueExtractor, checkValueExists, true); + } + + public SetSessionParamOperation(String paramName, ValueExtractor valueExtractor, boolean checkValueExists, boolean autocreate) { + Assert.notNull(paramName, "paramName"); + Assert.notNull(valueExtractor, "valueExtractor"); + + this.paramName = paramName; + this.valueExtractor = valueExtractor; + this.checkValueExists = checkValueExists; + this.autocreate = autocreate; + } + + @Override + public void process(HttpRequest req, HttpResponse resp, HttpFlowContext context) { + ParametersBag params = context.scopes().getSession(req, autocreate); + if (params != null) { + if (checkValueExists && params.contains(paramName)) { + return; + } + + Object value = HttpFiltersUtils.extractValue(valueExtractor, req, resp, context); + params.set(paramName, value); + } + } + + } + + private final List<Operation> operations = new ArrayList<>(); + + private HttpMessagePredicate predicate; + + public HttpMessagePredicate getPredicate() { + return predicate; + } + + public void setPredicate(HttpMessagePredicate predicate) { + this.predicate = predicate; + } + + public void addOperation(Operation operation) { + Assert.notNull(operation, "operation"); + operations.add(operation); + } + + public boolean removeOperation(Operation operation) { + Assert.notNull(operation, "operation"); + return operations.remove(operation); + } + + public void clearOperations() { + operations.clear(); + } + + @Override + public void configure(Configuration config) { + List<Operation> ops = (List<Operation>) config.get("operations"); + operations.clear(); + + if (ops != null) { + for (Operation op : ops) { + addOperation(op); + } + } + + predicate = (HttpMessagePredicate) config.get("applyIf", null); + } + + @Override + public int filterOutbound(HttpRequest req, HttpResponse resp, HttpFlowContext context) { + if (req != null && !operations.isEmpty()) { + boolean exec = true; + if (predicate != null) { + HttpMessageWrapper wrapper = new HttpMessageWrapper(req, resp, context); + exec = predicate.test(wrapper); + } + + if (exec) { + for (Operation op : operations) { + op.process(req, resp, context); + } + } + } + + return DUNNO; + } + + @Override + public HttpScopeModificationFilter instanceForWorker(int index) { + HttpScopeModificationFilter filter = new HttpScopeModificationFilter(); + filter.operations.addAll(operations); + filter.predicate = predicate; + return filter; + } + + public static class HttpScopeModificationFilterNodeDefCreator implements NodeDefinitionCreator { + + @Override + public NodeDefinition create() { + HeaderOperationNodeDefinition headerNodeDef = new HeaderOperationNodeDefinition( + valueDef() + ); + headerNodeDef.addParam(tupleDef("@autocreate", valueDefBool()).setRequired(false)); + + KeyNameVaryListNodeDefinition operationsDef = new KeyNameVaryListNodeDefinition() + .setNodeTransformer(new HttpScopeModificationFilterTransformer()) + .add("$removeSession", nullValueDef()) + .add("$removeSessionParam", valueDef()) + .add("$addSessionParam", headerNodeDef) + .add("$setSessionParam", headerNodeDef); + + return mapDef( + tupleDef("operations", operationsDef), + tupleDef("applyIf", new HttpFilterMessagePredicateNodeDefinition()).setRequired(false) + ); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpScopeModificationFilterTransformer.java Wed Aug 02 14:51:49 2017 +0200 @@ -0,0 +1,87 @@ +package com.passus.st.client.http.filter; + +import com.passus.config.CMapNode; +import com.passus.config.CNode; +import com.passus.config.CTupleNode; +import com.passus.config.CValueNode; +import static com.passus.config.ConfigurationUtils.extractBoolean; +import com.passus.config.NodeType; +import com.passus.config.schema.NodeTransformer; +import com.passus.config.validation.Errors; +import com.passus.st.client.http.filter.HttpScopeModificationFilter.Operation; +import com.passus.st.client.http.filter.HttpScopeModificationFilter.RemoveSessionOperation; +import com.passus.st.client.http.filter.HttpScopeModificationFilter.SetSessionParamOperation; +import static com.passus.st.validation.NodeValidationUtils.validateType; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * + * @author Mirosław Hawrot + */ +public class HttpScopeModificationFilterTransformer implements NodeTransformer { + + private SetSessionParamOperation createSetSessionParamOperation(CTupleNode tuple, Errors errors) { + if (validateType(tuple.getNode(), NodeType.MAP, errors)) { + CMapNode mapNode = (CMapNode) tuple.getNode(); + + boolean autocreate = false; + for(CTupleNode mapTupleNode: mapNode.getChildren()) { + switch(mapTupleNode.getName()) { + case "@autocreate": + autocreate = extractBoolean(mapTupleNode, errors); + break; + default: + + } + } + } + + return null; + } + + @Override + public Object transform(CNode node, Errors errors) { + CMapNode mapNode = (CMapNode) node; + + List<CTupleNode> tuples = mapNode.getChildren(); + List<Operation> operations; + if (tuples.isEmpty()) { + operations = Collections.EMPTY_LIST; + } else { + operations = new ArrayList<>(); + } + + for (CTupleNode tuple : tuples) { + String opName = tuple.getName(); + try { + errors.pushNestedPath(opName); + Operation op = null; + switch (opName.toLowerCase()) { + case "$removesession": + op = new RemoveSessionOperation(); + break; + case "$removesessionparam": + break; + case "$addsessionparam": + break; + case "$setsessionparam": + break; + default: + throw new IllegalStateException("Not supported operation '" + opName + "'."); + } + } finally { + errors.popNestedPath(); + } + } + + return new CValueNode(operations); + } + + @Override + public Object reverseTransform(CNode node, Errors errors) { + throw new UnsupportedOperationException("Not supported yet."); + } + +}
--- a/stress-tester/src/main/java/com/passus/st/config/HeaderOperationNodeDefinition.java Wed Aug 02 14:50:37 2017 +0200 +++ b/stress-tester/src/main/java/com/passus/st/config/HeaderOperationNodeDefinition.java Wed Aug 02 14:51:49 2017 +0200 @@ -65,7 +65,7 @@ addParam(tupleDef); return this; } - + public TupleNodeDefinition findParamTupleDef(String name) { if (paramsTuplesDef == null) { return null;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpScopeModificationFilterTest.java Wed Aug 02 14:51:49 2017 +0200 @@ -0,0 +1,138 @@ +package com.passus.st.client.http.filter; + +import com.passus.config.validation.Errors; +import com.passus.filter.UnmutableValueExtractor; +import com.passus.net.http.HttpRequest; +import com.passus.net.http.HttpRequestBuilder; +import com.passus.st.AppUtils; +import com.passus.st.client.http.HttpConsts; +import com.passus.st.client.http.HttpFlowContext; +import com.passus.st.client.http.HttpScopes; +import static com.passus.st.client.http.filter.HttpScopeModificationFilter.*; +import java.util.List; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.testng.AssertJUnit.*; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * + * @author Mirosław Hawrot + */ +public class HttpScopeModificationFilterTest { + + private final String sessionId = "sessionId"; + + @BeforeClass + public static void beforeClass() { + AppUtils.registerAll(); + } + + @AfterClass + public static void afterClass() { + AppUtils.unregisterAll(); + } + + private HttpRequest createRequest() { + return HttpRequestBuilder.get("http://test.com/path") + .tag(HttpConsts.TAG_SESSION_ID, sessionId) + .build(); + } + + private HttpFlowContext createMockContext() { + HttpFlowContext mockContext = mock(HttpFlowContext.class); + final HttpScopes scopes = new HttpScopes(); + when(mockContext.scopes()).thenReturn(scopes); + return mockContext; + } + + @Test + public void testRemoveSessionOperation() { + HttpScopeModificationFilter filter = new HttpScopeModificationFilter(); + filter.addOperation(new RemoveSessionOperation()); + + HttpFlowContext mockContext = createMockContext(); + HttpScopes scopes = mockContext.scopes(); + scopes.createSession(sessionId); + assertTrue(scopes.getSession(sessionId) != null); + + HttpRequest req = createRequest(); + filter.filterOutbound(req, null, mockContext); + assertTrue(scopes.getSession(sessionId, false) == null); + } + + @Test + public void testRemoveSessionParamOperation() { + HttpScopeModificationFilter filter = new HttpScopeModificationFilter(); + filter.addOperation(new RemoveSessionParamOperation("paramName")); + + HttpFlowContext mockContext = createMockContext(); + HttpScopes scopes = mockContext.scopes(); + scopes.createSession(sessionId).set("paramName", "paramValue"); + assertTrue(scopes.getSession(sessionId).contains("paramName")); + + HttpRequest req = createRequest(); + filter.filterOutbound(req, null, mockContext); + assertFalse(scopes.getSession(sessionId, false).contains("paramName")); + } + + @Test + public void testSetSessionParamOperation_CheckValueExists_Autocreate() { + HttpScopeModificationFilter filter = new HttpScopeModificationFilter(); + filter.addOperation(new SetSessionParamOperation("paramName", new UnmutableValueExtractor("paramValue"), true)); + + HttpFlowContext mockContext = createMockContext(); + HttpScopes scopes = mockContext.scopes(); + + HttpRequest req = createRequest(); + filter.filterOutbound(req, null, mockContext); + assertEquals("paramValue", scopes.getSession(sessionId, false).get("paramName")); + + filter.clearOperations(); + filter.addOperation(new SetSessionParamOperation("paramName", new UnmutableValueExtractor("newParamValue"), true)); + filter.filterOutbound(req, null, mockContext); + assertEquals("paramValue", scopes.getSession(sessionId, false).get("paramName")); + } + + @Test + public void testSetSessionParamOperation_NotCheckValueExists_Autocreate() { + HttpScopeModificationFilter filter = new HttpScopeModificationFilter(); + filter.addOperation(new SetSessionParamOperation("paramName", new UnmutableValueExtractor("paramValue"), false)); + + HttpFlowContext mockContext = createMockContext(); + HttpScopes scopes = mockContext.scopes(); + + HttpRequest req = createRequest(); + filter.filterOutbound(req, null, mockContext); + assertEquals("paramValue", scopes.getSession(sessionId, false).get("paramName")); + + filter.clearOperations(); + filter.addOperation(new SetSessionParamOperation("paramName", new UnmutableValueExtractor("newParamValue"), false)); + filter.filterOutbound(req, null, mockContext); + assertEquals("newParamValue", scopes.getSession(sessionId, false).get("paramName")); + } + + @Test + public void testConfiguration() throws Exception { + String filterConfig = "filters:\n" + + " - type: modifyScope\n" + + " operations:\n" + + " $removeSession: ~\n" + + " $removeSessionParam: ParaName\n" + + " $addSessionParam: \n" + + " NewParam: NewParamValue\n" + + " $setSessionParam: \n" + + " \"@autocreate\": true\n" + + " NewParam: NewParamValue \n"; + + Errors errors = new Errors(); + List<HttpFilter> filters = HttpFiltersConfigurator.getFilters(filterConfig, errors); + + errors.getAllErrors().forEach(System.out::println); + assertEquals(0, errors.getErrorCount()); + assertEquals(1, filters.size()); + assertTrue(filters.get(0) instanceof HttpScopeModificationFilter); + } +}